\n\n```\n\n### npm\n\n```bash\nnpm install monster-webmcp\n```\n\n```typescript\nimport { monstermcp } from 'monster-webmcp';\n\nconst mcp = new monstermcp();\n\nmcp.registertool({\n name: 'search',\n description: 'search the product catalog',\n inputschema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'search keyword' }\n },\n required: ['query']\n },\n execute: async (args) => {\n const results = await fetch(`/api/search?q=${args.query}`);\n const data = await results.json();\n return { content: [{ type: 'text', text: json.stringify(data) }] };\n }\n});\n```\n\n## api\n\n### `new monstermcp(options?)`\n\n| option | type | default | description |\n|--------|------|---------|-------------|\n| `webmcp` | `boolean` | `true` | use native `document.modelcontext` |\n| `polyfill` | `boolean` | `true` | fall back to polyfill |\n| `traditionalmcp` | `boolean` | `false` | enable http/sse mcp transport |\n| `mcptransport` | `mcptransportconfig` | \u2014 | http/sse transport config |\n| `declarative` | `boolean` | `true` | process html form attributes |\n| `allowedorigins` | `string[]` | `[]` | globally allowed origins |\n| `ratelimits` | `record` | `{}` | per-tool rate limits |\n| `defaultratelimit` | `ratelimitconfig` | `{maxrequests:100,windowms:60000}` | default rate limit |\n| `debug` | `boolean` | `false` | enable debug logging |\n\n### `registertool(tool, options?)`\n\nregister a tool with the runtime.\n\n```typescript\nmcp.registertool({\n name: 'my_tool', // 1-128 chars, alphanumeric/_/-/.\n title: 'my tool', // human-readable title\n description: 'what it does', // required\n inputschema: { // json schema\n type: 'object',\n properties: { /* ... */ },\n required: ['param1']\n },\n outputschema: { /* ... */ }, // optional\n annotations: { // optional safety hints\n readonlyhint: true,\n idempotenthint: true,\n },\n execute: async (args, signal) => {\n return {\n content: [{ type: 'text', text: 'result' }],\n iserror: false\n };\n }\n}, {\n signal: abortcontroller.signal, // abortsignal for lifecycle\n exposedto: ['https://agent.example.com'], // cross-origin opt-in\n ratelimit: { maxrequests: 50, windowms: 60000 }, // per-tool limit\n});\n```\n\n### `unregistertool(name)`\n\nremove a tool by name.\n\n### `gettools()`\n\nreturns an array of all registered tool info objects.\n\n### `executetool(name, args?)`\n\nexecute a tool by name with the given arguments.\n\n```typescript\nconst result = await mcp.executetool('greet', { name: 'world' });\n// result.content[0].text === \"hello, world!\"\n```\n\n### `ontoolchange(callback)`\n\nsubscribe to tool change events. returns an unsubscribe function.\n\n```typescript\nconst unsub = mcp.ontoolchange((event) => {\n console.log(event.type, event.toolname);\n // event.type: 'registered' | 'unregistered' | 'updated'\n});\n// later: unsub();\n```\n\n### `destroy()`\n\nclean up all resources, abort pending operations, and unregister all tools.\n\n## declarative html forms\n\nmonsterwebmcp automatically processes `
` elements with the `toolname` attribute:\n\n```html\n\n \n \n
\n```\n\n### supported attributes\n\n| attribute | element | description |\n|-----------|---------|-------------|\n| `toolname` | `
` | registers the form as a tool with this name |\n| `tooldescription` | `` | tool description |\n| `toolautosubmit` | `` | auto-submit form when tool is called |\n| `toolparamdescription` | ``, `