{"_id":"@ananay-nag/mcp-decorators","_rev":"3-248a8b9e57274589f9061c552638972c","name":"@ananay-nag/mcp-decorators","dist-tags":{"latest":"2.0.1"},"versions":{"1.0.0":{"name":"@ananay-nag/mcp-decorators","version":"1.0.0","keywords":[],"author":"","license":"ISC","_id":"@ananay-nag/mcp-decorators@1.0.0","maintainers":[{"name":"ananay-nag","email":"ananaynag1994s@gmail.com"}],"homepage":"https://mcp-decorators-doc.vercel.app/","bugs":{"url":"https://github.com/ananay-nag/mcp-decorators/issues"},"dist":{"shasum":"a86df9021d6e2f7bb9919e7726c371e4b1b41965","tarball":"https://registry.npmjs.org/@ananay-nag/mcp-decorators/-/mcp-decorators-1.0.0.tgz","fileCount":214,"integrity":"sha512-nrqNEYoBQb/MKVqH9gOHuJO7bLTS58PErSVUVB2BYdtoMYA8QxHiNluvWvbXgB3BGDTCHZhq4J7jOCyArOwalg==","signatures":[{"sig":"MEQCIFUsu05mIZ6ZiouCqncl0G6Vfv87/7CYlec0eA2N2mOTAiAs41mp7fHWytvmVbfAYyaepdBr5aS2XgQaVayplN/7kA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":264517},"main":"./dist/cjs/index.js","type":"module","types":"./dist/cjs/index.d.ts","module":"./dist/esm/index.js","engines":{"node":">=18"},"exports":{".":{"import":"./dist/esm/index.js","require":"./dist/cjs/index.js"},"./*":{"import":"./dist/esm/*","require":"./dist/cjs/*"}},"gitHead":"9ad7c75800f8d230b4c4f87d760e3ff47a7fd98d","scripts":{"build":"npm run build:esm && npm run build:cjs","build:cjs":"mkdir -p dist/cjs && echo '{\"type\": \"commonjs\"}' > dist/cjs/package.json && tsc -p tsconfig.cjs.json","build:esm":"mkdir -p dist/esm && echo '{\"type\": \"module\"}' > dist/esm/package.json && tsc -p tsconfig.prod.json","build:cjs:w":"npm run build:cjs -- -w","build:esm:w":"npm run build:esm -- -w","build:publish":"rm -rf dist/ *mcp*.tgz && npm run build && npm pack"},"_npmUser":{"name":"ananay-nag","email":"ananaynag1994s@gmail.com"},"repository":{"url":"git+https://github.com/ananay-nag/mcp-decorators.git","type":"git"},"_npmVersion":"11.16.0","description":"Model Context Protocol implementation for TypeScript with decorators","directories":{},"_nodeVersion":"24.18.0","dependencies":{"zod":"^3.23.8","zod-to-json-schema":"^3.24.1","@modelcontextprotocol/sdk":"^1.11.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/node":"^24.0.4"},"_npmOperationalInternal":{"tmp":"tmp/mcp-decorators_1.0.0_1783868935904_0.2202371427767964","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@ananay-nag/mcp-decorators","version":"2.0.0","keywords":["mcp","model-context-protocol","decorators","typescript","mcp-server","mcp-client","claude","ai","agents","llm","class-based","server","client","model","context","protocol"],"author":{"name":"Ananay Nag"},"license":"Apache-2.0","_id":"@ananay-nag/mcp-decorators@2.0.0","maintainers":[{"name":"ananay-nag","email":"ananaynag1994s@gmail.com"}],"homepage":"https://mcp-decorators-doc.vercel.app/","bugs":{"url":"https://github.com/ananay-nag/mcp-decorators/issues"},"dist":{"shasum":"874deee187c98ec4f7ebca83f24f974168e5ac7f","tarball":"https://registry.npmjs.org/@ananay-nag/mcp-decorators/-/mcp-decorators-2.0.0.tgz","fileCount":214,"integrity":"sha512-hk/rcDUEbJ7w5eHPWDKFWJexhY6jki+yPmGzn2GJ3/NwC65IPiAhxFWS63bg9tw5Ost4X+fazz+bT8vQd9AhwQ==","signatures":[{"sig":"MEUCIQDRNNb74DaULdEJ+pP2qvkux2lBh0P/CWRPoz1o+MG4jwIgA3JzOvolwxn3v9EBMIxL1685drlxrlucLuJwOrWNb+4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ananay-nag%2fmcp-decorators@2.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":250565},"main":"./dist/cjs/index.js","type":"module","types":"./dist/cjs/index.d.ts","module":"./dist/esm/index.js","engines":{"node":">=18"},"exports":{".":{"import":"./dist/esm/index.js","require":"./dist/cjs/index.js"},"./*":{"import":"./dist/esm/*","require":"./dist/cjs/*"}},"gitHead":"c4f6687256965a9ab10a19dddb798e73d25bfd52","scripts":{"test":"node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js","build":"npm run build:esm && npm run build:cjs","build:cjs":"mkdir -p dist/cjs && echo '{\"type\": \"commonjs\"}' > dist/cjs/package.json && tsc -p tsconfig.cjs.json","build:esm":"mkdir -p dist/esm && echo '{\"type\": \"module\"}' > dist/esm/package.json && tsc -p tsconfig.prod.json","build:cjs:w":"npm run build:cjs -- -w","build:esm:w":"npm run build:esm -- -w","build:publish":"rm -rf dist/ *mcp*.tgz && npm run build && npm pack","test:coverage":"node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js --coverage | node scripts/filter-coverage.js"},"_npmUser":{"name":"ananay-nag","email":"ananaynag1994s@gmail.com"},"repository":{"url":"git+https://github.com/ananay-nag/mcp-decorators.git","type":"git"},"_npmVersion":"10.8.2","description":"Model Context Protocol implementation for TypeScript with decorators","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^3.23.8","zod-to-json-schema":"^3.24.1","@modelcontextprotocol/sdk":"^1.11.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.4.2","ts-jest":"^29.4.11","@types/jest":"^30.0.0","@types/node":"^24.0.4"},"_npmOperationalInternal":{"tmp":"tmp/mcp-decorators_2.0.0_1783875523080_0.5923265085672129","host":"s3://npm-registry-packages-npm-production"}},"2.0.1":{"name":"@ananay-nag/mcp-decorators","version":"2.0.1","description":"Model Context Protocol implementation for TypeScript with decorators","type":"module","main":"./dist/cjs/index.js","module":"./dist/esm/index.js","types":"./dist/cjs/index.d.ts","engines":{"node":">=18"},"exports":{".":{"import":"./dist/esm/index.js","require":"./dist/cjs/index.js"},"./*":{"import":"./dist/esm/*","require":"./dist/cjs/*"}},"scripts":{"build:esm":"mkdir -p dist/esm && echo '{\"type\": \"module\"}' > dist/esm/package.json && tsc -p tsconfig.prod.json","build:esm:w":"npm run build:esm -- -w","build:cjs":"mkdir -p dist/cjs && echo '{\"type\": \"commonjs\"}' > dist/cjs/package.json && tsc -p tsconfig.cjs.json","build:cjs:w":"npm run build:cjs -- -w","build":"npm run build:esm && npm run build:cjs","build:publish":"rm -rf dist/ *mcp*.tgz && npm run build && npm pack","test":"node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js","test:coverage":"node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js --coverage | node scripts/filter-coverage.js"},"keywords":["mcp","model-context-protocol","decorators","typescript","mcp-server","mcp-client","claude","ai","agents","llm","class-based","server","client","model","context","protocol"],"author":{"name":"Ananay Nag"},"license":"Apache-2.0","dependencies":{"@modelcontextprotocol/sdk":"^1.11.0","zod":"^3.23.8","zod-to-json-schema":"^3.24.1"},"devDependencies":{"@types/jest":"^30.0.0","@types/node":"^24.0.4","jest":"^30.4.2","ts-jest":"^29.4.11"},"homepage":"https://mcp-decorators-doc.vercel.app/","repository":{"type":"git","url":"git+https://github.com/ananay-nag/mcp-decorators.git"},"_id":"@ananay-nag/mcp-decorators@2.0.1","gitHead":"bee7a47dc1dd03f26fbcafad43aa6032bd50adda","bugs":{"url":"https://github.com/ananay-nag/mcp-decorators/issues"},"_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-vEIT/Mk+j7qsnlVu8Q8/9sWXuZvaKh4B93XoodPl+mbQNlcE0GiSb9BzqrXZ+4IrlP1nkOPMII+uCq9XDTTRxw==","shasum":"505dff6b17a0226ffdb4058928acebfa55222bd6","tarball":"https://registry.npmjs.org/@ananay-nag/mcp-decorators/-/mcp-decorators-2.0.1.tgz","fileCount":214,"unpackedSize":250597,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ananay-nag%2fmcp-decorators@2.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIHzHC7uv1zaBrW1FKOKb9iYJa0ETizau6s6GvwGpElzsAiEAuLDb4nKJw+BP6Kyfdc5VZ4pPIWIqhFIEesUZSqRXCj0="}]},"_npmUser":{"name":"ananay-nag","email":"ananaynag1994s@gmail.com"},"directories":{},"maintainers":[{"name":"ananay-nag","email":"ananaynag1994s@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mcp-decorators_2.0.1_1783876037693_0.9332836707888879"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-12T15:08:55.741Z","modified":"2026-07-12T17:07:18.126Z","1.0.0":"2026-07-12T15:08:56.058Z","2.0.0":"2026-07-12T16:58:43.205Z","2.0.1":"2026-07-12T17:07:17.844Z"},"bugs":{"url":"https://github.com/ananay-nag/mcp-decorators/issues"},"author":{"name":"Ananay Nag"},"license":"Apache-2.0","homepage":"https://mcp-decorators-doc.vercel.app/","keywords":["mcp","model-context-protocol","decorators","typescript","mcp-server","mcp-client","claude","ai","agents","llm","class-based","server","client","model","context","protocol"],"repository":{"type":"git","url":"git+https://github.com/ananay-nag/mcp-decorators.git"},"description":"Model Context Protocol implementation for TypeScript with decorators","maintainers":[{"name":"ananay-nag","email":"ananaynag1994s@gmail.com"}],"readme":"# 🚀 MCP (Model Context Protocol) Decorators\n\n![MCP Decorators Banner](banner.svg)\n\n<p align=\"center\">\n  <a href=\"https://www.npmjs.com/package/@ananay-nag/mcp-decorators\">\n    <img src=\"https://img.shields.io/npm/v/@ananay-nag/mcp-decorators.svg?color=cb3837&style=flat-square\" alt=\"npm version\" />\n  </a>\n  <a href=\"https://www.npmjs.com/package/@ananay-nag/mcp-decorators\">\n    <img src=\"https://img.shields.io/node/v/@ananay-nag/mcp-decorators.svg?color=339933&style=flat-square\" alt=\"node compatibility\" />\n  </a>\n  <a href=\"https://github.com/ananay-nag/mcp-decorators/actions/workflows/test.yml\">\n    <img src=\"https://img.shields.io/github/actions/workflow/status/ananay-nag/mcp-decorators/test.yml.svg?style=flat-square\" alt=\"build status\" />\n  </a>\n  <a href=\"https://github.com/ananay-nag/mcp-decorators/issues\">\n    <img src=\"https://img.shields.io/github/issues/ananay-nag/mcp-decorators.svg?color=2ea44f&style=flat-square\" alt=\"github issues\" />\n  </a>\n  <a href=\"https://github.com/ananay-nag/mcp-decorators/blob/main/LICENSE\">\n    <img src=\"https://img.shields.io/github/license/ananay-nag/mcp-decorators.svg?color=6f42c1&style=flat-square\" alt=\"license\" />\n  </a>\n  <a href=\"https://mcp-decorators-doc.vercel.app/\">\n    <img src=\"https://img.shields.io/badge/Documentation-mcp--decorators-0969da.svg?style=flat-square\" alt=\"Documentation\" />\n  </a>\n</p>\n\nA powerful, TypeScript-native decorator library to simplify and supercharge your Model Context Protocol (MCP) server and client development.\n\n`@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.\n\n### [MCP Decorators - Documentation](https://mcp-decorators-doc.vercel.app/)\n\n---\n\n## Table of Contents\n1. [Installation & Configuration](#installation--configuration)\n2. [Server-Side Decorators](#server-side-decorators)\n   - [Core Class Decorators](#core-class-decorators)\n   - [MCP Capabilities Decorators](#mcp-capabilities-decorators)\n   - [Advanced Server Routing](#advanced-server-routing)\n3. [Full Server Example](#full-server-example)\n4. [Client-Side Decorators](#client-side-decorators)\n   - [Core Client Decorators](#core-client-decorators)\n   - [Client Call Wrapper Decorators](#client-call-wrapper-decorators)\n   - [Client Request/Notification Handlers](#client-requestnotification-handlers)\n5. [Full Client Example](#full-client-example)\n6. [Utilities](#utilities)\n7. [Testing](#testing)\n8. [Under the Hood & Advantages](#under-the-hood--advantages)\n\n---\n\n## Installation & Configuration\n\nInstall the package via npm:\n\n```bash\nnpm install @ananay-nag/mcp-decorators\n```\n\nEnsure that you have enabled decorator support in your `tsconfig.json`:\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true\n  }\n}\n```\n\n---\n\n## Server-Side Decorators\n\nServer-side decorators automate capability aggregation, map request dispatchers, manage client subscriptions, and route incoming requests and notifications.\n\n### Core Class Decorators\n\n#### 1. `@RegisterServer()`\n* **Target**: Class extending `Server` (from `@modelcontextprotocol/sdk/server/index.js`)\n* **Description**: Automatically registers the instantiated server in the global registry using the name and version passed to the class constructor.\n```typescript\nimport { Server, ServerOptions } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { RegisterServer } from \"@ananay-nag/mcp-decorators\";\nimport { Implementation } from \"@modelcontextprotocol/sdk/types.js\";\n\n@RegisterServer()\nexport class MyMCPServer extends Server {\n  constructor(serverInfo: Implementation, options?: ServerOptions) {\n    super(serverInfo, options);\n  }\n}\n```\n\n#### 2. `@UseServer(options)`\n* **Target**: Any handler/service class\n* **Parameters**: `options: { name: string; version?: string }`\n* **Description**: Injects the registered server instance into the class prototype as `this.server` and automatically binds all decorated handlers on class instantiation.\n```typescript\nimport { UseServer } from \"@ananay-nag/mcp-decorators\";\n\n@UseServer({ name: \"my-mcp-server\", version: \"2.0.1\" })\nexport class DbHandlers {\n  server: any; // Injected server instance\n}\n```\n\n---\n\n### MCP Capabilities Decorators\n\n#### 3. `@Tool(options)`\n* **Target**: Method\n* **Parameters**: `options: { name: string; description: string; inputSchema?: any }`\n* **Description**: Registers a method as an MCP Tool. Validates inputs automatically using the `inputSchema` (supports standard schemas or **Zod** schemas).\n```typescript\nimport { Tool } from \"@ananay-nag/mcp-decorators\";\nimport { z } from \"zod\";\n\n@Tool({\n  name: \"query_database\",\n  description: \"Run a read-only SQL query against the database\",\n  inputSchema: z.object({\n    sql: z.string(),\n  })\n})\nasync query(args: { sql: string }) {\n  // Method body receives the arguments object directly\n  return {\n    content: [{ type: \"text\", text: `Results for: ${args.sql}` }]\n  };\n}\n```\n\n#### 4. `@Prompt(options)`\n* **Target**: Method\n* **Parameters**: `options: { name: string; description?: string; arguments?: Array<{ name: string; description?: string; required?: boolean }> }`\n* **Description**: Exposes a prompt template to clients.\n```typescript\nimport { Prompt } from \"@ananay-nag/mcp-decorators\";\n\n@Prompt({\n  name: \"explain_code\",\n  description: \"Explain the provided code snippet\",\n  arguments: [{ name: \"code\", description: \"Source code to explain\", required: true }]\n})\nasync explainCode(args: { code: string }) {\n  return {\n    messages: [\n      { role: \"user\", content: { type: \"text\", text: `Please explain this code:\\n\\n${args.code}` } }\n    ]\n  };\n}\n```\n\n#### 5. `@Resource(options)` & `@ResourceTemplate(options)`\n* **Target**: Method\n* **Parameters**:\n  - `@Resource`: `options: { uri: string; name: string; description?: string; mimeType?: string }`\n  - `@ResourceTemplate`: `options: { uriTemplate: string; name: string; description?: string; mimeType?: string }`\n* **Description**: Expose static text/binary files or dynamic URI templates.\n```typescript\nimport { Resource, ResourceTemplate } from \"@ananay-nag/mcp-decorators\";\n\n// Exposes a static resource\n@Resource({\n  uri: \"mysql://schema/tables\",\n  name: \"Tables list schema\"\n})\nasync getTables() {\n  return { contents: [{ uri: \"mysql://schema/tables\", text: \"['users', 'orders']\" }] };\n}\n\n// Exposes dynamic URIs matching a template (e.g. mysql://users/schema)\n@ResourceTemplate({\n  uriTemplate: \"mysql://{tableName}/schema\",\n  name: \"Dynamic Table Schema\"\n})\nasync getTableSchema(params: { tableName: string }) {\n  // 'tableName' is automatically parsed from the requested URI and injected\n  return {\n    contents: [{ uri: `mysql://${params.tableName}/schema`, text: `Schema for ${params.tableName}` }]\n  };\n}\n```\n\n#### 6. `@Subscribe()` & `@Unsubscribe()`\n* **Target**: Methods\n* **Description**: Triggered when a client subscribes/unsubscribes to resource URI updates.\n```typescript\nimport { Subscribe, Unsubscribe } from \"@ananay-nag/mcp-decorators\";\n\n@Subscribe()\nasync onSubscribe(uri: string) {\n  console.log(`Client subscribed to resource updates on: ${uri}`);\n}\n\n@Unsubscribe()\nasync onUnsubscribe(uri: string) {\n  console.log(`Client unsubscribed from: ${uri}`);\n}\n```\n\n#### 7. `@Completion(ref)`\n* **Target**: Method\n* **Parameters**: `ref: { type: \"prompt\" | \"resource\"; name: string }`\n* **Description**: Registers auto-completion handler for a prompt argument or a resource template parameter.\n```typescript\nimport { Completion } from \"@ananay-nag/mcp-decorators\";\n\n@Completion({ type: \"prompt\", name: \"explain_code\" })\nasync autocompleteCodePrompt(args: { argument: string; value: string }) {\n  return {\n    completion: {\n      values: [\"typescript\", \"javascript\", \"python\"]\n    }\n  };\n}\n```\n\n---\n\n### Advanced Server Routing\n\n#### 8. `@RequestHandler(schema)` & `@NotificationHandler(schema)`\n* **Target**: Method\n* **Parameters**: `schema: string | ZodSchema`\n* **Description**: Low-level request and notification catch-alls. If a string is provided, it matches the JSON-RPC method name exactly.\n```typescript\nimport { RequestHandler, NotificationHandler } from \"@ananay-nag/mcp-decorators\";\n\n@NotificationHandler(\"notifications/initialized\")\nasync onClientInit(params: any) {\n  console.log(\"Client initialization completed!\");\n}\n```\n\n#### 9. `@ActionHandler(actionName)`\n* **Target**: Method\n* **Parameters**: `actionName: string`\n* **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.\n```typescript\nimport { RequestHandler, ActionHandler } from \"@ananay-nag/mcp-decorators\";\nimport { CallToolRequestSchema } from \"@modelcontextprotocol/sdk/types.js\";\n\nexport class RawHandlers {\n  // Routes tool calls for \"ping\" tool\n  @RequestHandler(CallToolRequestSchema)\n  @ActionHandler(\"ping\")\n  async handlePing(request: any) {\n    return { content: [{ type: \"text\", text: \"pong\" }] };\n  }\n\n  // Routes tool calls for \"query\" tool\n  @RequestHandler(CallToolRequestSchema)\n  @ActionHandler(\"query\")\n  async handleQuery(request: any) {\n    return { content: [{ type: \"text\", text: \"executing query...\" }] };\n  }\n}\n```\n\n---\n\n## Full Server Example\n\n### `server.ts`\n```typescript\nimport { Server, ServerOptions } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { RegisterServer } from \"@ananay-nag/mcp-decorators\";\nimport { Implementation } from \"@modelcontextprotocol/sdk/types.js\";\n\n@RegisterServer()\nexport class MyMCPServer extends Server {\n  constructor(serverInfo: Implementation, options?: ServerOptions) {\n    super(serverInfo, options);\n  }\n}\n```\n\n### `dbHandlers.ts`\n```typescript\nimport { UseServer, Tool, Resource, ResourceTemplate } from \"@ananay-nag/mcp-decorators\";\nimport { z } from \"zod\";\n\n@UseServer({ name: \"my-database-mcp\", version: \"2.0.1\" })\nexport class DbHandlers {\n  server: any; // Injected instance\n\n  @Tool({\n    name: \"fetch_users\",\n    description: \"Fetch list of active users\",\n    inputSchema: z.object({\n      limit: z.number().default(10)\n    })\n  })\n  async fetchUsers(args: { limit: number }) {\n    return {\n      content: [{ type: \"text\", text: `Fetched ${args.limit} users.` }]\n    };\n  }\n\n  @Resource({\n    uri: \"mysql://tables/list\",\n    name: \"MySQL Tables\",\n    description: \"List of tables in MySQL database\"\n  })\n  async listTables() {\n    return {\n      contents: [{ uri: \"mysql://tables/list\", text: JSON.stringify([\"users\", \"orders\", \"payments\"]) }]\n    };\n  }\n\n  @ResourceTemplate({\n    uriTemplate: \"mysql://{tableName}/schema\",\n    name: \"Table Schema Details\"\n  })\n  async getTableSchema(params: { tableName: string }) {\n    return {\n      contents: [{ uri: `mysql://${params.tableName}/schema`, text: `Fields details for ${params.tableName}` }]\n    };\n  }\n}\n```\n\n### `index.ts`\n```typescript\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { MyMCPServer } from \"./server.js\";\nimport { DbHandlers } from \"./dbHandlers.js\";\n\nasync function main() {\n  // 1. Create registered server instance\n  const server = new MyMCPServer(\n    { name: \"my-database-mcp\", version: \"2.0.1\" },\n    { capabilities: {} }\n  );\n\n  // 2. Instantiate handlers (binds decorators dynamically BEFORE connecting)\n  new DbHandlers();\n\n  // 3. Setup stdio transport and connect\n  const transport = new StdioServerTransport();\n  await server.connect(transport);\n  \n  console.error(\"🚀 MCP Server running on Stdio!\");\n}\n\nmain().catch(console.error);\n```\n\n---\n\n## Client-Side Decorators\n\nClient 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.\n\n### Core Client Decorators\n\n#### 1. `@RegisterClient()`\n* **Target**: Class extending `Client` (from `@modelcontextprotocol/sdk/client/index.js`)\n* **Description**: Registers the client instance in the global client registry upon construction.\n```typescript\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { RegisterClient } from \"@ananay-nag/mcp-decorators\";\n\n@RegisterClient()\nexport class MyMCPClient extends Client {}\n```\n\n#### 2. `@UseClient(options)`\n* **Target**: Client service/controller class\n* **Parameters**: `options: { name: string; version?: string }`\n* **Description**: Injects the registered client instance as `this.client` and binds all method capability wrappers.\n```typescript\nimport { UseClient } from \"@ananay-nag/mcp-decorators\";\n\n@UseClient({ name: \"my-mcp-client\" })\nexport class MyService {\n  client: any; // Injected\n}\n```\n\n---\n\n### Client Call Wrapper Decorators\n\nBy decorating a method in a `@UseClient` class, calling that method locally automatically triggers a request to the server. \n\n* **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.\n* **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.\n\n| Decorator | JSON-RPC Method | Description |\n| :--- | :--- | :--- |\n| **`@CallTool(name?)`** | `tools/call` | Calls a server tool. Uses method name if name is omitted. |\n| **`@ListTools()`** | `tools/list` | Lists all available tools on the server. |\n| **`@GetPrompt(name?)`** | `prompts/get` | Retrieves a specific prompt template. |\n| **`@ListPrompts()`** | `prompts/list` | Lists prompts available on the server. |\n| **`@ReadResource(uri?)`** | `resources/read` | Reads a resource. Direct URI parameter is supported. |\n| **`@ListResources()`** | `resources/list` | Lists resources available on the server. |\n| **`@ListResourceTemplates()`**| `resources/templates/list` | Lists dynamic resource templates. |\n| **`@SubscribeResource(uri?)`**| `resources/subscribe` | Subscribes to resource updates. |\n| **`@UnsubscribeResource(uri?)`**| `resources/unsubscribe` | Unsubscribes from resource updates. |\n| **`@CompletePromptOrResource()`**| `completion/complete` | Retrieves auto-completion values. |\n| **`@SetLoggingLevel(level?)`**| `logging/setLevel` | Sets server logging level. |\n| **`@PingServer()`** | `ping` | Pings the server. |\n\n---\n\n### Client Request/Notification Handlers\n\nClient classes decorated with `@UseClient` can also listen to requests and notifications sent from the server using:\n* `@RequestHandler(schema)`\n* `@NotificationHandler(schema)`\n\nFor instance, you can handle resource update notifications pushed by the server.\n\n```typescript\nimport { UseClient, NotificationHandler } from \"@ananay-nag/mcp-decorators\";\n\n@UseClient({ name: \"my-mcp-client\" })\nexport class LogController {\n  client: any;\n\n  // Handle resource updates pushed by the server\n  @NotificationHandler(\"notifications/resources/updated\")\n  async onResourceUpdate(params: { uri: string }) {\n    console.log(`⚠️ Server notified update for: ${params.uri}`);\n  }\n}\n```\n\n---\n\n## Full Client Example\n\n### `client.ts`\n```typescript\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { RegisterClient } from \"@ananay-nag/mcp-decorators\";\n\n@RegisterClient()\nexport class MyMCPClient extends Client {}\n```\n\n### `service.ts`\n```typescript\nimport { UseClient, CallTool, ListTools, ReadResource, NotificationHandler } from \"@ananay-nag/mcp-decorators\";\n\n@UseClient({ name: \"my-mcp-client\", version: \"2.0.1\" })\nexport class ClientController {\n  client: any; // Injected instance\n\n  // 1. Calling a tool named \"fetch_users\"\n  @CallTool(\"fetch_users\")\n  async fetchUsers(args: { limit: number }): Promise<any> {}\n\n  // 2. List tools on the server\n  @ListTools()\n  async getToolsList(): Promise<any> {}\n\n  // 3. Read a resource (Preprocesses parameter into URI schema)\n  @ReadResource()\n  async loadTableSchema(tableName: string) {\n    return `mysql://${tableName}/schema`; // Returns final argument sent to server\n  }\n\n  // 4. Handle notifications pushed from server\n  @NotificationHandler(\"notifications/resources/updated\")\n  onResourceUpdated(params: { uri: string }) {\n    console.log(`Resource changed on server: ${params.uri}`);\n  }\n}\n```\n\n### `index.ts`\n```typescript\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { MyMCPClient } from \"./client.js\";\nimport { ClientController } from \"./service.js\";\n\nasync function runClient() {\n  const client = new MyMCPClient(\n    { name: \"my-mcp-client\", version: \"2.0.1\" },\n    { capabilities: {} }\n  );\n\n  const transport = new StdioClientTransport({\n    command: \"node\",\n    args: [\"path/to/server/index.js\"]\n  });\n\n  await client.connect(transport);\n\n  // Initialize service to bind decorators\n  const controller = new ClientController();\n\n  // Test tool call\n  const users = await controller.fetchUsers({ limit: 5 });\n  console.log(\"Users output:\", users);\n\n  // Test resource read\n  const schema = await controller.loadTableSchema(\"users\");\n  console.log(\"Schema output:\", schema);\n}\n\nrunClient().catch(console.error);\n```\n\n---\n\n## Utilities\n\n#### 1. `notifyResourceUpdated(server, uri)`\nTriggers a push notification to all clients subscribed to the specified resource URI.\n```typescript\nimport { notifyResourceUpdated } from \"@ananay-nag/mcp-decorators\";\n\n// Pushes notification to clients subscribed to 'mysql://users/schema'\nawait notifyResourceUpdated(this.server, \"mysql://users/schema\");\n```\n\n#### 2. `sendProgress(server, progressToken, progress, total?, message?)`\nSend real-time progress updates back to the client during long-running tasks.\n```typescript\nimport { sendProgress } from \"@ananay-nag/mcp-decorators\";\n\n// Inside a Tool handler method:\nconst token = request._meta?.progressToken;\nif (token) {\n  await sendProgress(this.server, token, 1, 5, \"Processing part 1...\");\n}\n```\n\n#### 3. `sendLoggingMessage(server, level, data, logger?)`\nTransmits standard log notifications to the client over MCP.\n```typescript\nimport { sendLoggingMessage } from \"@ananay-nag/mcp-decorators\";\n\nawait sendLoggingMessage(this.server, \"info\", { query: \"SELECT * FROM users\" }, \"DatabaseLogger\");\n```\n\n#### 4. `elicitInput(server, params, options?)`\nPrompts the client/user for dynamic input or form submission mid-request.\n```typescript\nimport { elicitInput } from \"@ananay-nag/mcp-decorators\";\n\nconst response = await elicitInput(this.server, {\n  mode: \"form\",\n  message: \"Confirm table drop?\",\n  requestedSchema: {\n    type: \"object\",\n    properties: { confirm: { type: \"boolean\" } },\n    required: [\"confirm\"]\n  }\n});\n```\n\n#### 5. `getServer(options)`\nFetch a registered server instance programmatically.\n```typescript\nimport { getServer } from \"@ananay-nag/mcp-decorators\";\n\nconst server = getServer({ name: \"my-database-mcp\", version: \"2.0.1\" });\n```\n\n#### 6. `getClient(options)`\nFetch a registered client instance programmatically.\n```typescript\nimport { getClient } from \"@ananay-nag/mcp-decorators\";\n\nconst client = getClient({ name: \"my-mcp-client\", version: \"2.0.1\" });\n```\n\n---\n\n## Testing\n\nThis library uses **Jest** and **ts-jest** for clean, isolated decorator verification.\n\n### Running the Test Suite\n\n```bash\n# Run all test cases\nnpm run test\n\n# Run tests with coverage reporting (excludes uncovered line numbers column)\nnpm run test:coverage\n```\n\n### Test Coverage Summary\n\n<details>\n<summary>📊 Click to view full coverage report</summary>\n\n<!-- START_COVERAGE -->\n| File | % Stmts | % Branch | % Funcs | % Lines |\n| :--- | :--- | :--- | :--- | :--- |\n| All files | 70.12 | 52.12 | 61.36 | 70.47 |\n| client/decorators | 77.08 | 52.17 | 68 | 77.65 |\n| client.decorator.ts | 74.71 | 52.38 | 61.9 | 75.29 |\n| notification.decorator.ts | 100 | 50 | 100 | 100 |\n| requestHandler.decorator.ts | 100 | 50 | 100 | 100 |\n| client/utils | 70 | 62.5 | 75 | 68.42 |\n| clientRegistry.ts | 70 | 62.5 | 75 | 68.42 |\n| server/decorators | 72.8 | 53.15 | 62.5 | 73.25 |\n| action.decorator.ts | 100 | 100 | 100 | 100 |\n| completion.decorator.ts | 100 | 50 | 100 | 100 |\n| notification.decorator.ts | 100 | 50 | 100 | 100 |\n| prompt.decorator.ts | 100 | 50 | 100 | 100 |\n| requestHandler.decorator.ts | 100 | 100 | 100 | 100 |\n| resource.decorator.ts | 100 | 50 | 100 | 100 |\n| server.decorator.ts | 66.99 | 52.29 | 35.71 | 67.33 |\n| subscribe.decorator.ts | 100 | 100 | 100 | 100 |\n| tool.decorator.ts | 100 | 50 | 100 | 100 |\n| server/utils | 42.85 | 40 | 36.36 | 42.55 |\n| serverRegistry.ts | 42.85 | 40 | 36.36 | 42.55 |\n<!-- END_COVERAGE -->\n\n</details>\n\n---\n\n## Under the Hood & Advantages\n\n* **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.\n* **Zod Validation Integration**: Automatically processes typescript parameter typing or schema validations using Zod validator patterns on Tool inputSchemas.\n* **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.\n* **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.\n* **Dual CJS & ESM Compatibility**: Fully compiled for both exports setups to prevent TypeScript resolution errors in legacy standard node projects.","readmeFilename":"README.md"}