From 37ab59dadc6f9e66b931ef610abe9828900e62fd Mon Sep 17 00:00:00 2001 From: Patrik Simek Date: Fri, 24 Apr 2026 00:04:10 +0200 Subject: [PATCH] refactor(tools): harness-agnostic tool definitions --- AGENTS.md | 26 +-- README.md | 24 ++- package-lock.json | 20 +- package.json | 12 +- scripts/run-mcp-server.mjs | 6 +- ...onnections.mcp.ts => connections.tools.ts} | 10 + ...ts.mcp.ts => credential-requests.tools.ts} | 13 ++ ...rds.mcp.ts => data-store-records.tools.ts} | 7 + ...ata-stores.mcp.ts => data-stores.tools.ts} | 8 + ...ctures.mcp.ts => data-structures.tools.ts} | 8 + .../{devices.mcp.ts => devices.tools.ts} | 1 + .../{enums.mcp.ts => enums.tools.ts} | 3 + ...{executions.mcp.ts => executions.tools.ts} | 8 + .../{folders.mcp.ts => folders.tools.ts} | 6 + .../{functions.mcp.ts => functions.tools.ts} | 9 + .../{hooks.mcp.ts => hooks.tools.ts} | 8 + ....mcp.ts => incomplete-executions.tools.ts} | 3 + src/endpoints/{keys.mcp.ts => keys.tools.ts} | 8 + ...izations.mcp.ts => organizations.tools.ts} | 8 + .../{scenarios.mcp.ts => scenarios.tools.ts} | 18 ++ .../sdk/{apps.mcp.ts => apps.tools.ts} | 11 + ...onnections.mcp.ts => connections.tools.ts} | 9 + .../{functions.mcp.ts => functions.tools.ts} | 8 + .../sdk/{modules.mcp.ts => modules.tools.ts} | 7 + .../sdk/{rpcs.mcp.ts => rpcs.tools.ts} | 8 + .../{webhooks.mcp.ts => webhooks.tools.ts} | 7 + .../{teams.mcp.ts => teams.tools.ts} | 6 + .../{users.mcp.ts => users.tools.ts} | 1 + src/mcp.ts | 158 ++------------ src/tools.ts | 199 ++++++++++++++++++ test/mcp.spec.ts | 101 +++++++-- tsup.config.ts | 2 +- 32 files changed, 519 insertions(+), 204 deletions(-) rename src/endpoints/{connections.mcp.ts => connections.tools.ts} (95%) rename src/endpoints/{credential-requests.mcp.ts => credential-requests.tools.ts} (97%) rename src/endpoints/{data-store-records.mcp.ts => data-store-records.tools.ts} (96%) rename src/endpoints/{data-stores.mcp.ts => data-stores.tools.ts} (94%) rename src/endpoints/{data-structures.mcp.ts => data-structures.tools.ts} (95%) rename src/endpoints/{devices.mcp.ts => devices.tools.ts} (96%) rename src/endpoints/{enums.mcp.ts => enums.tools.ts} (94%) rename src/endpoints/{executions.mcp.ts => executions.tools.ts} (94%) rename src/endpoints/{folders.mcp.ts => folders.tools.ts} (94%) rename src/endpoints/{functions.mcp.ts => functions.tools.ts} (95%) rename src/endpoints/{hooks.mcp.ts => hooks.tools.ts} (95%) rename src/endpoints/{incomplete-executions.mcp.ts => incomplete-executions.tools.ts} (93%) rename src/endpoints/{keys.mcp.ts => keys.tools.ts} (95%) rename src/endpoints/{organizations.mcp.ts => organizations.tools.ts} (94%) rename src/endpoints/{scenarios.mcp.ts => scenarios.tools.ts} (95%) rename src/endpoints/sdk/{apps.mcp.ts => apps.tools.ts} (97%) rename src/endpoints/sdk/{connections.mcp.ts => connections.tools.ts} (97%) rename src/endpoints/sdk/{functions.mcp.ts => functions.tools.ts} (97%) rename src/endpoints/sdk/{modules.mcp.ts => modules.tools.ts} (98%) rename src/endpoints/sdk/{rpcs.mcp.ts => rpcs.tools.ts} (98%) rename src/endpoints/sdk/{webhooks.mcp.ts => webhooks.tools.ts} (97%) rename src/endpoints/{teams.mcp.ts => teams.tools.ts} (94%) rename src/endpoints/{users.mcp.ts => users.tools.ts} (95%) create mode 100644 src/tools.ts diff --git a/AGENTS.md b/AGENTS.md index 09bb1a1..2d0e7c1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,7 +11,7 @@ make-sdk/ ├── src/ │ ├── endpoints/ # API endpoint implementations │ │ ├── *.ts # Endpoints -│ │ └── *.mcp.ts # MCP Tools +│ │ └── *.tools.ts # Tool definitions (MCP / CLI / …) │ ├── index.ts # Main entry point with all exports │ ├── make.ts # Core Make client class │ ├── types.ts # Common type definitions @@ -518,13 +518,13 @@ export type ListEntityNamesOptions = { }; ``` -## MCP (Model Context Protocol) Integration +## Tool Definitions -The Make TypeScript SDK supports MCP tool integration to provide AI agents with access to all SDK functionality. This section covers the patterns and conventions for creating MCP tool definitions. +Every endpoint ships with a companion **tool definitions** file that describes its operations in a harness-agnostic shape. The same definitions power the MCP server (`@makehq/sdk/mcp`), the Make CLI, and any other integration that wants a uniform view of SDK operations — nothing here is specific to MCP. This section covers the patterns and conventions for creating those definitions. -### MCP File Structure +### Tool Definitions File Structure -**File Location**: `src/endpoints/{endpoint-name}.mcp.ts` or `src/endpoints/sdk/{endpoint-name}.mcp.ts` +**File Location**: `src/endpoints/{endpoint-name}.tools.ts` or `src/endpoints/sdk/{endpoint-name}.tools.ts` ```typescript import type { Make } from '../../make.js'; @@ -553,7 +553,7 @@ export const tools = [ ### Import Patterns -**Always use type imports** for MCP files since they only reference types: +**Always use type imports** for tool definition files since they only reference types: ```typescript // ✅ Correct - Type imports only @@ -724,11 +724,11 @@ export const tools = [ ]; ``` -### MCP Integration Checklist +### Tool Definitions Checklist -Before completing MCP tool definitions: +Before completing tool definitions: -- [ ] File uses `.mcp.ts` extension +- [ ] File uses `.tools.ts` extension - [ ] Uses `type` imports only (no runtime imports) - [ ] All tools follow the exact naming convention - [ ] Categories are properly hierarchical @@ -738,8 +738,9 @@ Before completing MCP tool definitions: - [ ] TypeScript types match the actual SDK method signatures - [ ] Descriptions are clear and helpful - [ ] All public SDK methods are covered +- [ ] New file is registered in `src/tools.ts` (the aggregator consumed by both `./tools` and `./mcp` exports) -### Common MCP Mistakes to Avoid +### Common Tool Definition Mistakes to Avoid 1. **Using runtime imports** - Always use `type` imports only 2. **Incorrect parameter extraction** - Ensure body parameters are properly separated @@ -748,8 +749,9 @@ Before completing MCP tool definitions: 5. **Wrong categories** - Use kebab-case for all categories, including SDK (e.g., `sdk-apps`, not `sdk.apps`) 6. **Missing descriptions** - Every parameter and tool needs clear documentation 7. **Type mismatches** - Ensure TypeScript types match actual SDK signatures -8. **Incomplete coverage** - All public methods should have corresponding MCP tools +8. **Incomplete coverage** - All public methods should have corresponding tool definitions +9. **Forgetting to register in `src/tools.ts`** - A new `*.tools.ts` file is only live once its `tools` array is spread into `MakeTools` -This MCP integration ensures that AI agents can access the full Make SDK functionality through a standardized protocol interface while maintaining type safety and clear documentation. +These tool definitions ensure that AI agents, CLIs, and other harnesses can access the full Make SDK functionality through a standardized shape while maintaining type safety and clear documentation. This guide ensures consistent, maintainable, and well-tested extensions to the Make TypeScript SDK. diff --git a/README.md b/README.md index 7ca3116..5b618d5 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ const make = new Make('your-api-key', 'eu2.make.com', { - Support for majority of Make API endpoints - Built-in error handling and response typing - Comprehensive test coverage -- Model Context Protocol (MCP) support +- Harness-agnostic tool definitions powering the [Make MCP Server](https://developers.make.com/mcp-server) and the [Make CLI](https://github.com/integromat/make-cli) ## Configuration Options @@ -124,21 +124,24 @@ The SDK supports automatic retries with exponential backoff for handling rate li The retry mechanism uses exponential backoff with jitter to prevent thundering herd problems. When a `Retry-After` header is present in the response, the SDK respects it (capped at `maxDelay`). -## MCP Server Support +## Tool Definitions -This SDK includes full support for the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/), allowing AI agents to interact with the Make API through standardized tools. All SDK endpoints are automatically exposed as MCP tools. +Every SDK endpoint is also described as a harness-agnostic **tool definition** - a self-contained record with a JSON Schema, examples, and an executor. The same definitions power: -### Integrating with MCP Server (experimental) +- the official [Make MCP Server](https://developers.make.com/mcp-server), +- the official [Make CLI](https://github.com/integromat/make-cli), +- and any future consumer. + +Import them directly via the `./tools` subpath: ```ts import { Make } from '@makehq/sdk'; -import { MakeMCPTools } from '@makehq/sdk/mcp'; +import { MakeTools } from '@makehq/sdk/tools'; -// Initialize the Make client const make = new Make('your-api-key', 'eu2.make.com'); // List tools -const tools = MakeMCPTools.map(tool => { +const tools = MakeTools.map(tool => { return { name: tool.name, title: tool.title, @@ -147,8 +150,8 @@ const tools = MakeMCPTools.map(tool => { }; }); -// Execute tool -const tool = MakeMCPTools.find(tool => tool.name === 'scenarios_list'); +// Execute a tool +const tool = MakeTools.find(tool => tool.name === 'scenarios_list'); try { await tool.execute(make, { teamId: 1 }); @@ -221,9 +224,10 @@ make-sdk/ ├── src/ # Source code │ ├── endpoints/ # API endpoint implementations │ │ ├── *.ts # Endpoints -│ │ └── *.mcp.ts # MCP Tools +│ │ └── *.tools.ts # Tool definitions (MCP / CLI / …) │ ├── index.ts # Main entry point │ ├── make.ts # Core Make client +│ ├── tools.ts # Aggregated tool definitions (./tools export) │ ├── types.ts # Common type definitions │ └── utils.ts # Utility functions ├── test/ # Test files diff --git a/package-lock.json b/package-lock.json index c8d1e7d..24fe0a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@makehq/sdk", - "version": "1.2.1", + "version": "1.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@makehq/sdk", - "version": "1.2.1", + "version": "1.3.0", "license": "MIT", "devDependencies": { "@eslint/js": "^9.22.0", @@ -77,7 +77,6 @@ "integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -2393,7 +2392,6 @@ "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~6.20.0" } @@ -2435,7 +2433,6 @@ "integrity": "sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.26.1", @@ -2466,7 +2463,6 @@ "integrity": "sha512-w6HZUV4NWxqd8BdeFf81t07d7/YV9s7TCWrQQbG5uhuvGUAW+fq1usZ1Hmz9UPNLniFnD8GLSsDpjP0hm1S4lQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/types": "8.26.1", @@ -2670,7 +2666,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3039,7 +3034,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -3694,7 +3688,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -3762,7 +3755,6 @@ "integrity": "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", @@ -4116,7 +4108,6 @@ "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", @@ -4656,7 +4647,6 @@ "integrity": "sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=16.9.0" } @@ -5050,7 +5040,6 @@ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -7457,7 +7446,6 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -7600,7 +7588,6 @@ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -7840,7 +7827,6 @@ "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -8104,7 +8090,6 @@ "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", "dev": true, "license": "ISC", - "peer": true, "bin": { "yaml": "bin.mjs" }, @@ -8173,7 +8158,6 @@ "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "dev": true, "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index 5002b90..bfb5971 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@makehq/sdk", - "version": "1.2.1", + "version": "1.3.0", "description": "Make TypeScript SDK", "license": "MIT", "author": "Make", @@ -35,6 +35,16 @@ "default": "./dist/index.cjs" } }, + "./tools": { + "import": { + "types": "./dist/tools.d.ts", + "default": "./dist/tools.js" + }, + "require": { + "types": "./dist/tools.d.cts", + "default": "./dist/tools.cjs" + } + }, "./mcp": { "import": { "types": "./dist/mcp.d.ts", diff --git a/scripts/run-mcp-server.mjs b/scripts/run-mcp-server.mjs index 6e2e0ea..8837107 100755 --- a/scripts/run-mcp-server.mjs +++ b/scripts/run-mcp-server.mjs @@ -7,7 +7,7 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js'; import { Make } from '../dist/index.js'; -import { MakeMCPTools } from '../dist/mcp.js'; +import { MakeTools } from '../dist/tools.js'; const server = new Server( { @@ -34,7 +34,7 @@ const make = new Make(process.env.MAKE_API_KEY, process.env.MAKE_ZONE); server.setRequestHandler(ListToolsRequestSchema, async () => { return { - tools: MakeMCPTools.map(tool => { + tools: MakeTools.map(tool => { return { name: tool.name, title: tool.title, @@ -46,7 +46,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => { }); server.setRequestHandler(CallToolRequestSchema, async request => { - const tool = MakeMCPTools.find(tool => tool.name === request.params.name); + const tool = MakeTools.find(tool => tool.name === request.params.name); if (!tool) { throw new Error(`Unknown tool: ${request.params.name}`); } diff --git a/src/endpoints/connections.mcp.ts b/src/endpoints/connections.tools.ts similarity index 95% rename from src/endpoints/connections.mcp.ts rename to src/endpoints/connections.tools.ts index 3803752..d1c0a85 100644 --- a/src/endpoints/connections.mcp.ts +++ b/src/endpoints/connections.tools.ts @@ -8,6 +8,7 @@ export const tools = [ description: 'List connections for a team.', category: 'connections', scope: 'connections:read', + scopeId: 'teamId', identifier: 'teamId', annotations: { readOnlyHint: true, @@ -46,7 +47,9 @@ export const tools = [ description: 'Get details of a specific connection.', category: 'connections', scope: 'connections:read', + scopeId: 'connectionId', identifier: 'connectionId', + resourceId: 'connectionId', annotations: { readOnlyHint: true, }, @@ -68,6 +71,7 @@ export const tools = [ description: 'Create a new connection.', category: 'connections', scope: 'connections:write', + scopeId: 'teamId', identifier: 'teamId', annotations: { idempotentHint: true, @@ -109,7 +113,9 @@ export const tools = [ description: "Update a connection's configuration data.", category: 'connections', scope: 'connections:write', + scopeId: 'connectionId', identifier: 'connectionId', + resourceId: 'connectionId', annotations: { idempotentHint: true, destructiveHint: true, @@ -143,7 +149,9 @@ export const tools = [ description: 'Verify if a connection is working correctly.', category: 'connections', scope: 'connections:write', + scopeId: 'connectionId', identifier: 'connectionId', + resourceId: 'connectionId', annotations: { idempotentHint: true, destructiveHint: false, @@ -168,7 +176,9 @@ export const tools = [ description: 'Delete a connection.', category: 'connections', scope: 'connections:write', + scopeId: 'connectionId', identifier: 'connectionId', + resourceId: 'connectionId', annotations: { destructiveHint: true, }, diff --git a/src/endpoints/credential-requests.mcp.ts b/src/endpoints/credential-requests.tools.ts similarity index 97% rename from src/endpoints/credential-requests.mcp.ts rename to src/endpoints/credential-requests.tools.ts index 389977d..f218abe 100644 --- a/src/endpoints/credential-requests.mcp.ts +++ b/src/endpoints/credential-requests.tools.ts @@ -8,6 +8,7 @@ export const tools = [ 'Retrieve a list of credential requests. Each request can contain multiple credentials (connections and API keys). Filter by team, user, provider, status, or name to find specific requests.', category: 'credential-requests', scope: 'credential-requests:read', + scopeId: 'teamId', identifier: 'teamId', annotations: { readOnlyHint: true, @@ -52,7 +53,9 @@ export const tools = [ 'Use this to check the state of credentials within a request.', category: 'credential-requests', scope: 'credential-requests:read', + scopeId: 'requestId', identifier: 'requestId', + resourceId: 'requestId', annotations: { readOnlyHint: true, }, @@ -76,7 +79,9 @@ export const tools = [ 'Any scenarios using connections from this request will lose access to the corresponding services. This action cannot be undone.', category: 'credential-requests', scope: 'credential-requests:write', + scopeId: 'requestId', identifier: 'requestId', + resourceId: 'requestId', annotations: { destructiveHint: true, }, @@ -102,7 +107,9 @@ export const tools = [ 'This operation is idempotent - declining an already-declined credential has no additional effect.', category: 'credential-requests', scope: 'credential-requests:write', + scopeId: 'credentialId', identifier: 'credentialId', + resourceId: 'credentialId', annotations: { idempotentHint: true, destructiveHint: true, @@ -129,7 +136,9 @@ export const tools = [ 'After deletion, the credential can be authorized again through the normal flow.', category: 'credential-requests', scope: 'credential-requests:write', + scopeId: 'credentialId', identifier: 'credentialId', + resourceId: 'credentialId', annotations: { idempotentHint: true, destructiveHint: true, @@ -154,6 +163,7 @@ export const tools = [ 'This will return a URL where the user can authorize the credentials, so that they can be used in scenarios.', category: 'credential-requests', scope: 'credential-requests:write', + scopeId: 'teamId', identifier: 'teamId', annotations: { idempotentHint: true, @@ -247,6 +257,7 @@ export const tools = [ 'At least one connection or one key must be provided.', category: 'credential-requests', scope: 'credential-requests:write', + scopeId: 'teamId', identifier: 'teamId', annotations: { idempotentHint: true, @@ -401,7 +412,9 @@ export const tools = [ 'Fails if all requested scopes are already present on the connection.', category: 'credential-requests', scope: 'credential-requests:write', + scopeId: 'connectionId', identifier: 'connectionId', + resourceId: 'connectionId', annotations: { idempotentHint: true, destructiveHint: false, diff --git a/src/endpoints/data-store-records.mcp.ts b/src/endpoints/data-store-records.tools.ts similarity index 96% rename from src/endpoints/data-store-records.mcp.ts rename to src/endpoints/data-store-records.tools.ts index 734fb88..2fd8cea 100644 --- a/src/endpoints/data-store-records.mcp.ts +++ b/src/endpoints/data-store-records.tools.ts @@ -8,6 +8,7 @@ export const tools = [ description: 'List all records in a data store.', category: 'data-store-records', scope: 'datastores:read', + scopeId: 'dataStoreId', identifier: 'dataStoreId', annotations: { readOnlyHint: true, @@ -31,6 +32,7 @@ export const tools = [ description: 'Create a new record in a data store.', category: 'data-store-records', scope: 'datastores:write', + scopeId: 'dataStoreId', identifier: 'dataStoreId', annotations: { idempotentHint: true, @@ -65,7 +67,9 @@ export const tools = [ description: 'Update an existing record in a data store.', category: 'data-store-records', scope: 'datastores:write', + scopeId: 'dataStoreId', identifier: 'dataStoreId', + resourceId: 'key', annotations: { idempotentHint: true, destructiveHint: true, @@ -90,7 +94,9 @@ export const tools = [ description: "Replace an existing record in a data store or create if it doesn't exist.", category: 'data-store-records', scope: 'datastores:write', + scopeId: 'dataStoreId', identifier: 'dataStoreId', + resourceId: 'key', annotations: { idempotentHint: true, destructiveHint: true, @@ -121,6 +127,7 @@ export const tools = [ description: 'Delete specific records from a data store by keys.', category: 'data-store-records', scope: 'datastores:write', + scopeId: 'dataStoreId', identifier: 'dataStoreId', annotations: { destructiveHint: true, diff --git a/src/endpoints/data-stores.mcp.ts b/src/endpoints/data-stores.tools.ts similarity index 94% rename from src/endpoints/data-stores.mcp.ts rename to src/endpoints/data-stores.tools.ts index e6af4a6..aee92bf 100644 --- a/src/endpoints/data-stores.mcp.ts +++ b/src/endpoints/data-stores.tools.ts @@ -7,6 +7,7 @@ export const tools = [ description: 'List all data stores for a team.', category: 'data-stores', scope: 'datastores:read', + scopeId: 'teamId', identifier: 'teamId', annotations: { readOnlyHint: true, @@ -29,7 +30,9 @@ export const tools = [ description: 'Get data store details by ID.', category: 'data-stores', scope: 'datastores:read', + scopeId: 'dataStoreId', identifier: 'dataStoreId', + resourceId: 'dataStoreId', annotations: { readOnlyHint: true, }, @@ -51,6 +54,7 @@ export const tools = [ description: 'Create a new data store.', category: 'data-stores', scope: 'datastores:write', + scopeId: 'teamId', identifier: 'teamId', annotations: { idempotentHint: true, @@ -83,7 +87,9 @@ export const tools = [ description: 'Update a data store.', category: 'data-stores', scope: 'datastores:write', + scopeId: 'dataStoreId', identifier: 'dataStoreId', + resourceId: 'dataStoreId', annotations: { idempotentHint: true, destructiveHint: true, @@ -113,7 +119,9 @@ export const tools = [ description: 'Delete a data store.', category: 'data-stores', scope: 'datastores:write', + scopeId: 'dataStoreId', identifier: 'dataStoreId', + resourceId: 'dataStoreId', annotations: { destructiveHint: true, }, diff --git a/src/endpoints/data-structures.mcp.ts b/src/endpoints/data-structures.tools.ts similarity index 95% rename from src/endpoints/data-structures.mcp.ts rename to src/endpoints/data-structures.tools.ts index 960fc85..a760fcf 100644 --- a/src/endpoints/data-structures.mcp.ts +++ b/src/endpoints/data-structures.tools.ts @@ -8,6 +8,7 @@ export const tools = [ description: 'List data structures for a team.', category: 'data-structures', scope: 'udts:read', + scopeId: 'teamId', identifier: 'teamId', annotations: { readOnlyHint: true, @@ -30,7 +31,9 @@ export const tools = [ description: 'Get details of a specific data structure.', category: 'data-structures', scope: 'udts:read', + scopeId: 'dataStructureId', identifier: 'dataStructureId', + resourceId: 'dataStructureId', annotations: { readOnlyHint: true, }, @@ -52,6 +55,7 @@ export const tools = [ description: 'Create a new data structure.', category: 'data-structures', scope: 'udts:write', + scopeId: 'teamId', identifier: 'teamId', annotations: { idempotentHint: true, @@ -105,7 +109,9 @@ export const tools = [ description: 'Update an existing data structure.', category: 'data-structures', scope: 'udts:write', + scopeId: 'dataStructureId', identifier: 'dataStructureId', + resourceId: 'dataStructureId', annotations: { idempotentHint: true, destructiveHint: true, @@ -150,7 +156,9 @@ export const tools = [ description: 'Delete a data structure.', category: 'data-structures', scope: 'udts:write', + scopeId: 'dataStructureId', identifier: 'dataStructureId', + resourceId: 'dataStructureId', annotations: { destructiveHint: true, }, diff --git a/src/endpoints/devices.mcp.ts b/src/endpoints/devices.tools.ts similarity index 96% rename from src/endpoints/devices.mcp.ts rename to src/endpoints/devices.tools.ts index 5f7331d..5b2e80d 100644 --- a/src/endpoints/devices.mcp.ts +++ b/src/endpoints/devices.tools.ts @@ -7,6 +7,7 @@ export const tools = [ description: 'List devices registered in a team.', category: 'devices', scope: 'devices:read', + scopeId: 'teamId', identifier: 'teamId', annotations: { readOnlyHint: true, diff --git a/src/endpoints/enums.mcp.ts b/src/endpoints/enums.tools.ts similarity index 94% rename from src/endpoints/enums.mcp.ts rename to src/endpoints/enums.tools.ts index 9a45f06..3d0acdc 100644 --- a/src/endpoints/enums.mcp.ts +++ b/src/endpoints/enums.tools.ts @@ -7,6 +7,7 @@ export const tools = [ description: 'List all available countries.', category: 'enums', scope: undefined, + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -26,6 +27,7 @@ export const tools = [ description: 'List all available regions.', category: 'enums', scope: undefined, + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -45,6 +47,7 @@ export const tools = [ description: 'List all available timezones.', category: 'enums', scope: undefined, + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, diff --git a/src/endpoints/executions.mcp.ts b/src/endpoints/executions.tools.ts similarity index 94% rename from src/endpoints/executions.mcp.ts rename to src/endpoints/executions.tools.ts index 129bf45..e359ef4 100644 --- a/src/endpoints/executions.mcp.ts +++ b/src/endpoints/executions.tools.ts @@ -7,6 +7,7 @@ export const tools = [ description: 'List executions for a scenario.', category: 'executions', scope: 'scenarios:read', + scopeId: 'scenarioId', identifier: 'scenarioId', annotations: { readOnlyHint: true, @@ -33,7 +34,9 @@ export const tools = [ description: 'Get detailed result of a specific execution.', category: 'executions', scope: 'scenarios:read', + scopeId: 'scenarioId', identifier: 'scenarioId', + resourceId: 'executionId', annotations: { readOnlyHint: true, }, @@ -56,7 +59,9 @@ export const tools = [ description: 'Get details of a specific execution.', category: 'executions', scope: 'scenarios:read', + scopeId: 'scenarioId', identifier: 'scenarioId', + resourceId: 'executionId', annotations: { readOnlyHint: true, }, @@ -79,6 +84,7 @@ export const tools = [ description: 'List executions for an incomplete execution.', category: 'executions', scope: 'dlqs:read', + scopeId: 'incompleteExecutionId', identifier: 'incompleteExecutionId', annotations: { readOnlyHint: true, @@ -106,7 +112,9 @@ export const tools = [ description: 'Get execution details for an incomplete execution.', category: 'executions', scope: 'dlqs:read', + scopeId: 'incompleteExecutionId', identifier: 'incompleteExecutionId', + resourceId: 'executionId', annotations: { readOnlyHint: true, }, diff --git a/src/endpoints/folders.mcp.ts b/src/endpoints/folders.tools.ts similarity index 94% rename from src/endpoints/folders.mcp.ts rename to src/endpoints/folders.tools.ts index a1b58a2..3c90147 100644 --- a/src/endpoints/folders.mcp.ts +++ b/src/endpoints/folders.tools.ts @@ -7,6 +7,7 @@ export const tools = [ description: 'List folders for a team.', category: 'folders', scope: 'scenarios:read', + scopeId: 'teamId', identifier: 'teamId', annotations: { readOnlyHint: true, @@ -29,6 +30,7 @@ export const tools = [ description: 'Create a new folder.', category: 'folders', scope: 'scenarios:write', + scopeId: 'teamId', identifier: 'teamId', annotations: { idempotentHint: true, @@ -53,7 +55,9 @@ export const tools = [ description: 'Update an existing folder.', category: 'folders', scope: 'scenarios:write', + scopeId: 'folderId', identifier: 'folderId', + resourceId: 'folderId', annotations: { idempotentHint: true, destructiveHint: true, @@ -78,7 +82,9 @@ export const tools = [ description: 'Delete a folder.', category: 'folders', scope: 'scenarios:write', + scopeId: 'folderId', identifier: 'folderId', + resourceId: 'folderId', annotations: { destructiveHint: true, }, diff --git a/src/endpoints/functions.mcp.ts b/src/endpoints/functions.tools.ts similarity index 95% rename from src/endpoints/functions.mcp.ts rename to src/endpoints/functions.tools.ts index 893681c..fb342f0 100644 --- a/src/endpoints/functions.mcp.ts +++ b/src/endpoints/functions.tools.ts @@ -7,6 +7,7 @@ export const tools = [ description: 'List custom functions for a team.', category: 'functions', scope: 'functions:read', + scopeId: 'teamId', identifier: 'teamId', annotations: { readOnlyHint: true, @@ -29,7 +30,9 @@ export const tools = [ description: 'Get details of a specific custom function.', category: 'functions', scope: 'functions:read', + scopeId: 'functionId', identifier: 'functionId', + resourceId: 'functionId', annotations: { readOnlyHint: true, }, @@ -51,6 +54,7 @@ export const tools = [ description: 'Create a new custom function.', category: 'functions', scope: 'functions:write', + scopeId: 'teamId', identifier: 'teamId', annotations: { idempotentHint: true, @@ -88,7 +92,9 @@ export const tools = [ description: 'Update an existing custom function.', category: 'functions', scope: 'functions:write', + scopeId: 'functionId', identifier: 'functionId', + resourceId: 'functionId', annotations: { idempotentHint: true, destructiveHint: true, @@ -124,7 +130,9 @@ export const tools = [ description: 'Delete a custom function.', category: 'functions', scope: 'functions:write', + scopeId: 'functionId', identifier: 'functionId', + resourceId: 'functionId', annotations: { destructiveHint: true, }, @@ -147,6 +155,7 @@ export const tools = [ description: 'Check the syntax of a function without saving it.', category: 'functions', scope: 'functions:write', + scopeId: 'teamId', identifier: 'teamId', annotations: { readOnlyHint: true, diff --git a/src/endpoints/hooks.mcp.ts b/src/endpoints/hooks.tools.ts similarity index 95% rename from src/endpoints/hooks.mcp.ts rename to src/endpoints/hooks.tools.ts index 72426d2..80fa4c0 100644 --- a/src/endpoints/hooks.mcp.ts +++ b/src/endpoints/hooks.tools.ts @@ -8,6 +8,7 @@ export const tools = [ description: 'List webhooks/mailhooks for a specific team.', category: 'hooks', scope: 'hooks:read', + scopeId: 'teamId', identifier: 'teamId', annotations: { readOnlyHint: true, @@ -30,7 +31,9 @@ export const tools = [ description: 'Get details of a specific webhook/mailhook.', category: 'hooks', scope: 'hooks:read', + scopeId: 'hookId', identifier: 'hookId', + resourceId: 'hookId', annotations: { readOnlyHint: true, }, @@ -52,6 +55,7 @@ export const tools = [ description: 'Create a new webhook/mailhook.', category: 'hooks', scope: 'hooks:write', + scopeId: 'teamId', identifier: 'teamId', annotations: { idempotentHint: true, @@ -89,7 +93,9 @@ export const tools = [ description: 'Update an existing webhook/mailhook.', category: 'hooks', scope: 'hooks:write', + scopeId: 'hookId', identifier: 'hookId', + resourceId: 'hookId', annotations: { idempotentHint: true, destructiveHint: true, @@ -114,7 +120,9 @@ export const tools = [ description: 'Delete a webhook/mailhook.', category: 'hooks', scope: 'hooks:write', + scopeId: 'hookId', identifier: 'hookId', + resourceId: 'hookId', annotations: { destructiveHint: true, }, diff --git a/src/endpoints/incomplete-executions.mcp.ts b/src/endpoints/incomplete-executions.tools.ts similarity index 93% rename from src/endpoints/incomplete-executions.mcp.ts rename to src/endpoints/incomplete-executions.tools.ts index d35dd26..63dbb4e 100644 --- a/src/endpoints/incomplete-executions.mcp.ts +++ b/src/endpoints/incomplete-executions.tools.ts @@ -7,6 +7,7 @@ export const tools = [ description: 'List all incomplete executions.', category: 'incomplete-executions', scope: 'dlqs:read', + scopeId: 'scenarioId', identifier: 'scenarioId', annotations: { readOnlyHint: true, @@ -29,7 +30,9 @@ export const tools = [ description: 'Get details of a specific incomplete execution.', category: 'incomplete-executions', scope: 'dlqs:read', + scopeId: 'incompleteExecutionId', identifier: 'incompleteExecutionId', + resourceId: 'incompleteExecutionId', annotations: { readOnlyHint: true, }, diff --git a/src/endpoints/keys.mcp.ts b/src/endpoints/keys.tools.ts similarity index 95% rename from src/endpoints/keys.mcp.ts rename to src/endpoints/keys.tools.ts index 9a7ab6b..7da25cf 100644 --- a/src/endpoints/keys.mcp.ts +++ b/src/endpoints/keys.tools.ts @@ -8,6 +8,7 @@ export const tools = [ description: 'List all keys for a team.', category: 'keys', scope: 'keys:read', + scopeId: 'teamId', identifier: 'teamId', annotations: { readOnlyHint: true, @@ -30,7 +31,9 @@ export const tools = [ description: 'Get details of a specific key.', category: 'keys', scope: 'keys:read', + scopeId: 'keyId', identifier: 'keyId', + resourceId: 'keyId', annotations: { readOnlyHint: true, }, @@ -52,6 +55,7 @@ export const tools = [ description: 'Create a new key.', category: 'keys', scope: 'keys:write', + scopeId: 'teamId', identifier: 'teamId', annotations: { idempotentHint: true, @@ -88,7 +92,9 @@ export const tools = [ description: 'Update an existing key.', category: 'keys', scope: 'keys:write', + scopeId: 'keyId', identifier: 'keyId', + resourceId: 'keyId', annotations: { idempotentHint: true, destructiveHint: true, @@ -115,7 +121,9 @@ export const tools = [ description: 'Delete a key.', category: 'keys', scope: 'keys:write', + scopeId: 'keyId', identifier: 'keyId', + resourceId: 'keyId', annotations: { destructiveHint: true, }, diff --git a/src/endpoints/organizations.mcp.ts b/src/endpoints/organizations.tools.ts similarity index 94% rename from src/endpoints/organizations.mcp.ts rename to src/endpoints/organizations.tools.ts index 4f1e477..b4a3552 100644 --- a/src/endpoints/organizations.mcp.ts +++ b/src/endpoints/organizations.tools.ts @@ -7,6 +7,7 @@ export const tools = [ description: 'List organizations for the current user.', category: 'organizations', scope: 'organizations:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -26,7 +27,9 @@ export const tools = [ description: 'Get details of a specific organization.', category: 'organizations', scope: 'organizations:read', + scopeId: 'organizationId', identifier: 'organizationId', + resourceId: 'organizationId', annotations: { readOnlyHint: true, }, @@ -48,6 +51,7 @@ export const tools = [ description: 'Create a new organization.', category: 'organizations', scope: 'organizations:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, @@ -77,7 +81,9 @@ export const tools = [ description: 'Update an existing organization.', category: 'organizations', scope: 'organizations:write', + scopeId: 'organizationId', identifier: 'organizationId', + resourceId: 'organizationId', annotations: { idempotentHint: true, destructiveHint: true, @@ -112,7 +118,9 @@ export const tools = [ description: 'Delete an organization.', category: 'organizations', scope: 'organizations:write', + scopeId: 'organizationId', identifier: 'organizationId', + resourceId: 'organizationId', annotations: { destructiveHint: true, }, diff --git a/src/endpoints/scenarios.mcp.ts b/src/endpoints/scenarios.tools.ts similarity index 95% rename from src/endpoints/scenarios.mcp.ts rename to src/endpoints/scenarios.tools.ts index a03c52c..100c509 100644 --- a/src/endpoints/scenarios.mcp.ts +++ b/src/endpoints/scenarios.tools.ts @@ -10,6 +10,7 @@ export const tools = [ description: 'List all scenarios for a team.', category: 'scenarios', scope: 'scenarios:read', + scopeId: 'teamId', identifier: 'teamId', annotations: { readOnlyHint: true, @@ -32,7 +33,9 @@ export const tools = [ description: 'Get a scenario and its blueprint by ID.', category: 'scenarios', scope: 'scenarios:read', + scopeId: 'scenarioId', identifier: 'scenarioId', + resourceId: 'scenarioId', annotations: { readOnlyHint: true, }, @@ -60,6 +63,7 @@ export const tools = [ description: 'Create a new scenario.', category: 'scenarios', scope: 'scenarios:write', + scopeId: 'teamId', identifier: 'teamId', annotations: { idempotentHint: true, @@ -109,7 +113,9 @@ export const tools = [ description: 'Update a scenario.', category: 'scenarios', scope: 'scenarios:write', + scopeId: 'scenarioId', identifier: 'scenarioId', + resourceId: 'scenarioId', annotations: { idempotentHint: true, destructiveHint: true, @@ -159,7 +165,9 @@ export const tools = [ description: 'Delete a scenario.', category: 'scenarios', scope: 'scenarios:write', + scopeId: 'scenarioId', identifier: 'scenarioId', + resourceId: 'scenarioId', annotations: { destructiveHint: true, }, @@ -182,7 +190,9 @@ export const tools = [ description: 'Activate a scenario.', category: 'scenarios', scope: 'scenarios:write', + scopeId: 'scenarioId', identifier: 'scenarioId', + resourceId: 'scenarioId', annotations: { idempotentHint: true, destructiveHint: false, @@ -207,7 +217,9 @@ export const tools = [ description: 'Deactivate a scenario.', category: 'scenarios', scope: 'scenarios:write', + scopeId: 'scenarioId', identifier: 'scenarioId', + resourceId: 'scenarioId', annotations: { idempotentHint: true, destructiveHint: false, @@ -232,7 +244,9 @@ export const tools = [ description: 'Execute a scenario with optional input data.', category: 'scenarios', scope: 'scenarios:run', + scopeId: 'scenarioId', identifier: 'scenarioId', + resourceId: 'scenarioId', annotations: { destructiveHint: true, }, @@ -261,7 +275,9 @@ export const tools = [ description: 'Get the interface for a scenario.', category: 'scenarios', scope: 'scenarios:read', + scopeId: 'scenarioId', identifier: 'scenarioId', + resourceId: 'scenarioId', annotations: { readOnlyHint: true, }, @@ -283,7 +299,9 @@ export const tools = [ description: 'Update the interface for a scenario.', category: 'scenarios', scope: 'scenarios:write', + scopeId: 'scenarioId', identifier: 'scenarioId', + resourceId: 'scenarioId', annotations: { idempotentHint: true, destructiveHint: false, diff --git a/src/endpoints/sdk/apps.mcp.ts b/src/endpoints/sdk/apps.tools.ts similarity index 97% rename from src/endpoints/sdk/apps.mcp.ts rename to src/endpoints/sdk/apps.tools.ts index 8ddfb02..0328617 100644 --- a/src/endpoints/sdk/apps.mcp.ts +++ b/src/endpoints/sdk/apps.tools.ts @@ -8,6 +8,7 @@ export const tools = [ description: 'List SDK apps with optional filtering.', category: 'sdk-apps', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -27,6 +28,7 @@ export const tools = [ description: 'Get a SDK app by name and version.', category: 'sdk-apps', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -50,6 +52,7 @@ export const tools = [ description: 'Create a new SDK app.', category: 'sdk-apps', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, @@ -105,6 +108,7 @@ export const tools = [ description: 'Update an existing SDK app.', category: 'sdk-apps', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, @@ -152,6 +156,7 @@ export const tools = [ description: 'Delete a SDK app by name and version.', category: 'sdk-apps', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { destructiveHint: true, @@ -176,6 +181,7 @@ export const tools = [ description: 'Get a specific section of a SDK app.', category: 'sdk-apps', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -207,6 +213,7 @@ export const tools = [ description: 'Set/update a specific section of a SDK app.', category: 'sdk-apps', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, @@ -246,6 +253,7 @@ export const tools = [ description: 'Get app documentation (readme).', category: 'sdk-apps', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -269,6 +277,7 @@ export const tools = [ description: 'Set app documentation (readme).', category: 'sdk-apps', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, @@ -295,6 +304,7 @@ export const tools = [ description: 'Get app common data (client credentials and shared configuration).', category: 'sdk-apps', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -318,6 +328,7 @@ export const tools = [ description: 'Set app common data (client credentials and shared configuration).', category: 'sdk-apps', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, diff --git a/src/endpoints/sdk/connections.mcp.ts b/src/endpoints/sdk/connections.tools.ts similarity index 97% rename from src/endpoints/sdk/connections.mcp.ts rename to src/endpoints/sdk/connections.tools.ts index 420965d..572b120 100644 --- a/src/endpoints/sdk/connections.mcp.ts +++ b/src/endpoints/sdk/connections.tools.ts @@ -8,6 +8,7 @@ export const tools = [ description: 'List connections for a specific app.', category: 'sdk-connections', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -30,6 +31,7 @@ export const tools = [ description: 'Get a single connection by name.', category: 'sdk-connections', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -52,6 +54,7 @@ export const tools = [ description: 'Create a new connection for a specific app.', category: 'sdk-connections', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, @@ -78,6 +81,7 @@ export const tools = [ description: 'Update an existing connection.', category: 'sdk-connections', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, @@ -103,6 +107,7 @@ export const tools = [ description: 'Delete a connection.', category: 'sdk-connections', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { destructiveHint: true, @@ -126,6 +131,7 @@ export const tools = [ description: 'Get a specific section of a connection.', category: 'sdk-connections', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -159,6 +165,7 @@ export const tools = [ description: 'Set a specific section of a connection.', category: 'sdk-connections', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, @@ -202,6 +209,7 @@ export const tools = [ description: 'Get common configuration for a connection.', category: 'sdk-connections', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -224,6 +232,7 @@ export const tools = [ description: 'Set common configuration for a connection.', category: 'sdk-connections', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, diff --git a/src/endpoints/sdk/functions.mcp.ts b/src/endpoints/sdk/functions.tools.ts similarity index 97% rename from src/endpoints/sdk/functions.mcp.ts rename to src/endpoints/sdk/functions.tools.ts index f345cc9..39a4c20 100644 --- a/src/endpoints/sdk/functions.mcp.ts +++ b/src/endpoints/sdk/functions.tools.ts @@ -7,6 +7,7 @@ export const tools = [ description: 'List functions for the app.', category: 'sdk-functions', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -30,6 +31,7 @@ export const tools = [ description: 'Get a single function by name.', category: 'sdk-functions', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -54,6 +56,7 @@ export const tools = [ description: 'Create a new function.', category: 'sdk-functions', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, @@ -80,6 +83,7 @@ export const tools = [ description: 'Delete a function.', category: 'sdk-functions', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { destructiveHint: true, @@ -105,6 +109,7 @@ export const tools = [ description: 'Get function code.', category: 'sdk-functions', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -129,6 +134,7 @@ export const tools = [ description: 'Set/update function code.', category: 'sdk-functions', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, @@ -166,6 +172,7 @@ export const tools = [ description: 'Get function test code.', category: 'sdk-functions', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -190,6 +197,7 @@ export const tools = [ description: 'Set/update function test code.', category: 'sdk-functions', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, diff --git a/src/endpoints/sdk/modules.mcp.ts b/src/endpoints/sdk/modules.tools.ts similarity index 98% rename from src/endpoints/sdk/modules.mcp.ts rename to src/endpoints/sdk/modules.tools.ts index fae44d6..ad6b6fd 100644 --- a/src/endpoints/sdk/modules.mcp.ts +++ b/src/endpoints/sdk/modules.tools.ts @@ -7,6 +7,7 @@ export const tools = [ description: 'List modules for the app with optional filtering.', category: 'sdk-modules', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -30,6 +31,7 @@ export const tools = [ description: 'Get a single module by name.', category: 'sdk-modules', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -54,6 +56,7 @@ export const tools = [ description: 'Create a new module.', category: 'sdk-modules', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, @@ -108,6 +111,7 @@ export const tools = [ description: 'Update an existing module.', category: 'sdk-modules', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, @@ -147,6 +151,7 @@ export const tools = [ description: 'Delete a module.', category: 'sdk-modules', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { destructiveHint: true, @@ -172,6 +177,7 @@ export const tools = [ description: 'Get a specific section of a module.', category: 'sdk-modules', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -209,6 +215,7 @@ export const tools = [ description: 'Set/update a specific section of a module.', category: 'sdk-modules', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, diff --git a/src/endpoints/sdk/rpcs.mcp.ts b/src/endpoints/sdk/rpcs.tools.ts similarity index 98% rename from src/endpoints/sdk/rpcs.mcp.ts rename to src/endpoints/sdk/rpcs.tools.ts index 17cabee..79c0458 100644 --- a/src/endpoints/sdk/rpcs.mcp.ts +++ b/src/endpoints/sdk/rpcs.tools.ts @@ -8,6 +8,7 @@ export const tools = [ description: 'List all RPCs for the app.', category: 'sdk-rpcs', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -31,6 +32,7 @@ export const tools = [ description: 'Get a single RPC by name.', category: 'sdk-rpcs', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -55,6 +57,7 @@ export const tools = [ description: 'Create a new RPC.', category: 'sdk-rpcs', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, @@ -82,6 +85,7 @@ export const tools = [ description: 'Update an existing RPC.', category: 'sdk-rpcs', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, @@ -121,6 +125,7 @@ export const tools = [ description: 'Delete an RPC.', category: 'sdk-rpcs', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { destructiveHint: true, @@ -146,6 +151,7 @@ export const tools = [ description: 'Test an RPC with provided data and schema.', category: 'sdk-rpcs', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { destructiveHint: true, @@ -206,6 +212,7 @@ export const tools = [ description: 'Get RPC section data.', category: 'sdk-rpcs', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -243,6 +250,7 @@ export const tools = [ description: 'Set RPC section data.', category: 'sdk-rpcs', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, diff --git a/src/endpoints/sdk/webhooks.mcp.ts b/src/endpoints/sdk/webhooks.tools.ts similarity index 97% rename from src/endpoints/sdk/webhooks.mcp.ts rename to src/endpoints/sdk/webhooks.tools.ts index 7699f3f..d5457ad 100644 --- a/src/endpoints/sdk/webhooks.mcp.ts +++ b/src/endpoints/sdk/webhooks.tools.ts @@ -7,6 +7,7 @@ export const tools = [ description: 'List webhooks for a specific app.', category: 'sdk-webhooks', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -29,6 +30,7 @@ export const tools = [ description: 'Get a single webhook by name.', category: 'sdk-webhooks', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -51,6 +53,7 @@ export const tools = [ description: 'Create a new webhook for an app.', category: 'sdk-webhooks', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, @@ -77,6 +80,7 @@ export const tools = [ description: 'Update an existing webhook.', category: 'sdk-webhooks', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, @@ -102,6 +106,7 @@ export const tools = [ description: 'Delete a webhook.', category: 'sdk-webhooks', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { destructiveHint: true, @@ -125,6 +130,7 @@ export const tools = [ description: 'Get a specific section of a webhook.', category: 'sdk-webhooks', scope: 'sdk-apps:read', + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, @@ -158,6 +164,7 @@ export const tools = [ description: 'Set a specific section of a webhook.', category: 'sdk-webhooks', scope: 'sdk-apps:write', + scopeId: undefined, identifier: undefined, annotations: { idempotentHint: true, diff --git a/src/endpoints/teams.mcp.ts b/src/endpoints/teams.tools.ts similarity index 94% rename from src/endpoints/teams.mcp.ts rename to src/endpoints/teams.tools.ts index a5012ab..2105695 100644 --- a/src/endpoints/teams.mcp.ts +++ b/src/endpoints/teams.tools.ts @@ -7,6 +7,7 @@ export const tools = [ description: 'List teams for the current user.', category: 'teams', scope: 'teams:read', + scopeId: 'organizationId', identifier: 'organizationId', annotations: { readOnlyHint: true, @@ -29,7 +30,9 @@ export const tools = [ description: 'Get details of a specific team.', category: 'teams', scope: 'teams:read', + scopeId: 'teamId', identifier: 'teamId', + resourceId: 'teamId', annotations: { readOnlyHint: true, }, @@ -51,6 +54,7 @@ export const tools = [ description: 'Create a new team.', category: 'teams', scope: 'teams:write', + scopeId: 'organizationId', identifier: 'organizationId', annotations: { idempotentHint: true, @@ -83,7 +87,9 @@ export const tools = [ description: 'Delete a team.', category: 'teams', scope: 'teams:write', + scopeId: 'teamId', identifier: 'teamId', + resourceId: 'teamId', annotations: { destructiveHint: true, }, diff --git a/src/endpoints/users.mcp.ts b/src/endpoints/users.tools.ts similarity index 95% rename from src/endpoints/users.mcp.ts rename to src/endpoints/users.tools.ts index 80e29dd..043d91b 100644 --- a/src/endpoints/users.mcp.ts +++ b/src/endpoints/users.tools.ts @@ -7,6 +7,7 @@ export const tools = [ description: 'Get details of the current user.', category: 'users', scope: undefined, + scopeId: undefined, identifier: undefined, annotations: { readOnlyHint: true, diff --git a/src/mcp.ts b/src/mcp.ts index d6ada1d..e561b92 100644 --- a/src/mcp.ts +++ b/src/mcp.ts @@ -1,152 +1,20 @@ -import type { Make } from './make.js'; -import type { JSONValue } from './types.js'; +import { MakeTools, type MakeTool } from './tools.js'; -import { tools as SDKAppsTools } from './endpoints/sdk/apps.mcp.js'; -import { tools as SDKConnectionsTools } from './endpoints/sdk/connections.mcp.js'; -import { tools as SDKFunctionsTools } from './endpoints/sdk/functions.mcp.js'; -import { tools as SDKModulesTools } from './endpoints/sdk/modules.mcp.js'; -import { tools as SDKRPCsTools } from './endpoints/sdk/rpcs.mcp.js'; -import { tools as SDKWebhooksTools } from './endpoints/sdk/webhooks.mcp.js'; - -import { tools as ScenariosTools } from './endpoints/scenarios.mcp.js'; -import { tools as ConnectionsTools } from './endpoints/connections.mcp.js'; -import { tools as CredentialRequestsTools } from './endpoints/credential-requests.mcp.js'; -import { tools as DataStoresTools } from './endpoints/data-stores.mcp.js'; -import { tools as DataStoreRecordsTools } from './endpoints/data-store-records.mcp.js'; -import { tools as TeamsTools } from './endpoints/teams.mcp.js'; -import { tools as OrganizationsTools } from './endpoints/organizations.mcp.js'; -import { tools as UsersTools } from './endpoints/users.mcp.js'; -import { tools as FunctionsTools } from './endpoints/functions.mcp.js'; -import { tools as ExecutionsTools } from './endpoints/executions.mcp.js'; -import { tools as HooksTools } from './endpoints/hooks.mcp.js'; -import { tools as DevicesTools } from './endpoints/devices.mcp.js'; -import { tools as KeysTools } from './endpoints/keys.mcp.js'; -import { tools as FoldersTools } from './endpoints/folders.mcp.js'; -import { tools as IncompleteExecutionsTools } from './endpoints/incomplete-executions.mcp.js'; -import { tools as DataStructuresTools } from './endpoints/data-structures.mcp.js'; -import { tools as EnumsTools } from './endpoints/enums.mcp.js'; +export type { JSONSchema } from './tools.js'; /** - * JSON Schema definition for input parameters. + * Interface for MCP (Model Context Protocol) tools. + * + * @deprecated Use `MakeTool` from `@makehq/sdk/tools` instead. `MakeTool` is the + * canonical, harness-agnostic shape used by both the MCP server and the Make + * CLI. This alias is kept for backward compatibility. */ -export type JSONSchema = { - /** The type of the schema (object, string, number, boolean, array, etc.) */ - type: 'object' | 'string' | 'number' | 'boolean' | 'array' | 'null'; - /** Properties definition for object types */ - properties?: Record; - /** Required property names for object types */ - required?: string[]; - /** Items schema for array types */ - items?: JSONSchema; - /** Description of the schema or property */ - description?: string; - /** Enum values for restricted choices */ - enum?: JSONValue[]; - /** Default value */ - default?: JSONValue; - /** Minimum value for numbers */ - minimum?: number; - /** Maximum value for numbers */ - maximum?: number; - /** Minimum length for strings/arrays */ - minLength?: number; - /** Maximum length for strings/arrays */ - maxLength?: number; - /** Pattern for string validation */ - pattern?: string; -}; +export type MakeMCPTool = MakeTool; /** - * Interface for MCP (Model Context Protocol) tools. - * Defines the structure and behavior of tools that can be executed by AI agents. + * Aggregated list of tools exposed to MCP consumers. + * + * @deprecated Use `MakeTools` from `@makehq/sdk/tools` instead. The underlying + * definitions are identical; this alias is kept for backward compatibility. */ -export type MakeMCPTool = { - /** Unique identifier for the tool */ - name: string; - - /** Human-readable title for display purposes */ - title: string; - - /** Detailed description of what the tool does */ - description: string; - - /** Category for organizing tools (e.g., 'scenarios', 'teams', 'sdk.apps') */ - category: string; - - /** Required scope/permission for executing this tool */ - scope?: string; - - /** - * Field name used as the primary identifier for this tool's operations. - * Used for resource identification and access control. - */ - identifier?: string; - - /** Behavioral hints about the tool's operations */ - annotations?: { - /** - * If true, the tool may perform destructive updates to its environment. - * If false, the tool performs only additive updates. - * This property is meaningful only when readOnlyHint == false. - * @default true - */ - destructiveHint?: boolean; - - /** - * If true, calling the tool repeatedly with the same arguments will have - * no additional effect on its environment. - * This property is meaningful only when readOnlyHint == false. - * @default false - */ - idempotentHint?: boolean; - - /** - * If true, the tool does not modify its environment. - * @default false - */ - readOnlyHint?: boolean; - }; - - /** JSON Schema defining the input parameters */ - inputSchema: JSONSchema; - - /** Example input payloads illustrating how to use the tool */ - examples?: Record[]; - - /** - * Function that executes the tool's operation. - * @param make The Make SDK client instance - * @param args The input arguments matching the inputSchema - * @returns Promise resolving to the operation result - */ - execute: (make: Make, args?: Record) => Promise; -}; - -export const MakeMCPTools = [ - // SDK Tools - ...SDKAppsTools, - ...SDKConnectionsTools, - ...SDKFunctionsTools, - ...SDKModulesTools, - ...SDKRPCsTools, - ...SDKWebhooksTools, - - // Core Endpoint Tools - ...ScenariosTools, - ...ExecutionsTools, - ...IncompleteExecutionsTools, - ...FoldersTools, - ...FunctionsTools, - ...HooksTools, - ...DevicesTools, - ...DataStructuresTools, - ...ConnectionsTools, - ...KeysTools, - ...CredentialRequestsTools, - ...DataStoresTools, - ...DataStoreRecordsTools, - ...TeamsTools, - ...OrganizationsTools, - ...UsersTools, - ...EnumsTools, -] as MakeMCPTool[]; +export const MakeMCPTools: MakeTool[] = MakeTools; diff --git a/src/tools.ts b/src/tools.ts new file mode 100644 index 0000000..bac7075 --- /dev/null +++ b/src/tools.ts @@ -0,0 +1,199 @@ +import type { Make } from './make.js'; +import type { JSONValue } from './types.js'; + +import { tools as SDKAppsTools } from './endpoints/sdk/apps.tools.js'; +import { tools as SDKConnectionsTools } from './endpoints/sdk/connections.tools.js'; +import { tools as SDKFunctionsTools } from './endpoints/sdk/functions.tools.js'; +import { tools as SDKModulesTools } from './endpoints/sdk/modules.tools.js'; +import { tools as SDKRPCsTools } from './endpoints/sdk/rpcs.tools.js'; +import { tools as SDKWebhooksTools } from './endpoints/sdk/webhooks.tools.js'; + +import { tools as ScenariosTools } from './endpoints/scenarios.tools.js'; +import { tools as ConnectionsTools } from './endpoints/connections.tools.js'; +import { tools as CredentialRequestsTools } from './endpoints/credential-requests.tools.js'; +import { tools as DataStoresTools } from './endpoints/data-stores.tools.js'; +import { tools as DataStoreRecordsTools } from './endpoints/data-store-records.tools.js'; +import { tools as TeamsTools } from './endpoints/teams.tools.js'; +import { tools as OrganizationsTools } from './endpoints/organizations.tools.js'; +import { tools as UsersTools } from './endpoints/users.tools.js'; +import { tools as FunctionsTools } from './endpoints/functions.tools.js'; +import { tools as ExecutionsTools } from './endpoints/executions.tools.js'; +import { tools as HooksTools } from './endpoints/hooks.tools.js'; +import { tools as DevicesTools } from './endpoints/devices.tools.js'; +import { tools as KeysTools } from './endpoints/keys.tools.js'; +import { tools as FoldersTools } from './endpoints/folders.tools.js'; +import { tools as IncompleteExecutionsTools } from './endpoints/incomplete-executions.tools.js'; +import { tools as DataStructuresTools } from './endpoints/data-structures.tools.js'; +import { tools as EnumsTools } from './endpoints/enums.tools.js'; + +/** + * JSON Schema definition for input parameters. + */ +export type JSONSchema = { + /** The type of the schema (object, string, number, boolean, array, etc.) */ + type: 'object' | 'string' | 'number' | 'boolean' | 'array' | 'null'; + /** Properties definition for object types */ + properties?: Record; + /** Required property names for object types */ + required?: string[]; + /** Items schema for array types */ + items?: JSONSchema; + /** Description of the schema or property */ + description?: string; + /** Enum values for restricted choices */ + enum?: JSONValue[]; + /** Default value */ + default?: JSONValue; + /** Minimum value for numbers */ + minimum?: number; + /** Maximum value for numbers */ + maximum?: number; + /** Minimum length for strings/arrays */ + minLength?: number; + /** Maximum length for strings/arrays */ + maxLength?: number; + /** Pattern for string validation */ + pattern?: string; +}; + +/** + * Harness-agnostic definition of a Make SDK tool. + * + * A tool describes a single callable operation backed by the Make SDK. The same + * definitions power the MCP server, the Make CLI, and any future integrations + * (OpenAPI, LLM function calling, etc.) — nothing in this shape is specific to + * MCP. + */ +export type MakeTool = { + /** Unique identifier for the tool */ + name: string; + + /** Human-readable title for display purposes */ + title: string; + + /** Detailed description of what the tool does */ + description: string; + + /** Category for organizing tools (e.g., 'scenarios', 'teams', 'sdk.apps') */ + category: string; + + /** Required scope/permission for executing this tool */ + scope?: string; + + /** + * Input-schema property that names the **scope** this tool runs in — + * typically the parent / routing id consumers use for API routing and + * access control (e.g. `teamId`, `organizationId`, or `scenarioId` for a + * sub-resource). + * + * Distinct from {@link resourceId}, which names the single resource the + * tool acts on. A single tool may have both: + * - `executions_get`: `scopeId = 'scenarioId'`, `resourceId = 'executionId'` + * - `data-structures_get`: `scopeId = 'dataStructureId'`, `resourceId = 'dataStructureId'` + * + * Distinct also from {@link scope}, which is the OAuth permission string + * required to run the tool (e.g. `scenarios:read`); `scopeId` names the + * input property, `scope` names the permission. + * + * The value SHOULD be a key in {@link inputSchema}.properties when set. + */ + scopeId?: string; + + /** + * @deprecated Use {@link scopeId} instead. Kept as an alias for backward + * compatibility with consumers built against earlier SDK versions. When + * both are set they MUST have the same value. + */ + identifier?: string; + + /** + * Input-schema property that names the **resource** this tool operates on. + * + * Populate when the tool acts on a single, already-existing resource + * (get/update/delete/run-style actions). Leave undefined for + * collection-scoped actions (list/create) and for tools that don't act + * on a single resource (e.g. auth, health, enums). + * + * The value MUST be a key in {@link inputSchema}.properties. + * + * Distinct from {@link scopeId}, which names the scope/parent id used for + * client routing and access control. A single tool may have both: + * - `executions_get`: `scopeId = 'scenarioId'`, `resourceId = 'executionId'` + * - `data-structures_get`: `scopeId = 'dataStructureId'`, `resourceId = 'dataStructureId'` + */ + resourceId?: string; + + /** Behavioral hints about the tool's operations */ + annotations?: { + /** + * If true, the tool may perform destructive updates to its environment. + * If false, the tool performs only additive updates. + * This property is meaningful only when readOnlyHint == false. + * @default true + */ + destructiveHint?: boolean; + + /** + * If true, calling the tool repeatedly with the same arguments will have + * no additional effect on its environment. + * This property is meaningful only when readOnlyHint == false. + * @default false + */ + idempotentHint?: boolean; + + /** + * If true, the tool does not modify its environment. + * @default false + */ + readOnlyHint?: boolean; + }; + + /** JSON Schema defining the input parameters */ + inputSchema: JSONSchema; + + /** Example input payloads illustrating how to use the tool */ + examples?: Record[]; + + /** + * Function that executes the tool's operation. + * @param make The Make SDK client instance + * @param args The input arguments matching the inputSchema + * @returns Promise resolving to the operation result + */ + execute: (make: Make, args?: Record) => Promise; +}; + +/** + * Aggregated list of every tool definition exposed by the Make SDK. + * + * Consumed by the MCP server (via `./mcp`), the Make CLI, and any other harness + * that wants a uniform view of SDK operations. + */ +export const MakeTools = [ + // SDK Tools + ...SDKAppsTools, + ...SDKConnectionsTools, + ...SDKFunctionsTools, + ...SDKModulesTools, + ...SDKRPCsTools, + ...SDKWebhooksTools, + + // Core Endpoint Tools + ...ScenariosTools, + ...ExecutionsTools, + ...IncompleteExecutionsTools, + ...FoldersTools, + ...FunctionsTools, + ...HooksTools, + ...DevicesTools, + ...DataStructuresTools, + ...ConnectionsTools, + ...KeysTools, + ...CredentialRequestsTools, + ...DataStoresTools, + ...DataStoreRecordsTools, + ...TeamsTools, + ...OrganizationsTools, + ...UsersTools, + ...EnumsTools, +] as MakeTool[]; diff --git a/test/mcp.spec.ts b/test/mcp.spec.ts index 50d2a07..b4d146c 100644 --- a/test/mcp.spec.ts +++ b/test/mcp.spec.ts @@ -1,21 +1,21 @@ import { describe, expect, it } from '@jest/globals'; -import { MakeMCPTools } from '../src/mcp.js'; +import { MakeTools } from '../src/tools.js'; describe('MCP Tools', () => { - it('Should export MakeMCPTools array', () => { - expect(MakeMCPTools).toBeDefined(); - expect(Array.isArray(MakeMCPTools)).toBe(true); - expect(MakeMCPTools.length).toBeGreaterThan(0); + it('Should export MakeTools array', () => { + expect(MakeTools).toBeDefined(); + expect(Array.isArray(MakeTools)).toBe(true); + expect(MakeTools.length).toBeGreaterThan(0); }); it('Should have a reasonable number of tools', () => { // With all the endpoints, we should have a significant number of tools - expect(MakeMCPTools.length).toBeGreaterThan(50); - expect(MakeMCPTools.length).toBeLessThan(500); // Sanity check + expect(MakeTools.length).toBeGreaterThan(50); + expect(MakeTools.length).toBeLessThan(500); // Sanity check }); it('Should have tools with required properties', () => { - MakeMCPTools.forEach(tool => { + MakeTools.forEach(tool => { // Test required properties exist expect(tool).toHaveProperty('name'); expect(tool).toHaveProperty('title'); @@ -47,7 +47,7 @@ describe('MCP Tools', () => { }); it('Should have unique tool names', () => { - const names = MakeMCPTools.map(tool => tool.name); + const names = MakeTools.map(tool => tool.name); const uniqueNames = new Set(names); expect(uniqueNames.size).toBe(names.length); @@ -69,7 +69,7 @@ describe('MCP Tools', () => { }); it('Should have tools from SDK endpoints', () => { - const sdkTools = MakeMCPTools.filter(tool => tool.category.startsWith('sdk-')); + const sdkTools = MakeTools.filter(tool => tool.category.startsWith('sdk-')); expect(sdkTools.length).toBeGreaterThan(0); // Check for expected SDK categories @@ -83,7 +83,7 @@ describe('MCP Tools', () => { }); it('Should have tools from core endpoints', () => { - const coreTools = MakeMCPTools.filter(tool => !tool.category.startsWith('sdk-')); + const coreTools = MakeTools.filter(tool => !tool.category.startsWith('sdk-')); expect(coreTools.length).toBeGreaterThan(0); // Check for some expected core categories @@ -95,7 +95,7 @@ describe('MCP Tools', () => { }); it('Should have proper naming conventions', () => { - MakeMCPTools.forEach(tool => { + MakeTools.forEach(tool => { // Tool names should follow the pattern: {endpoint}_{action} or sdk_{endpoint}_{action} const namePattern = /^(sdk_)?[a-z_-]+_[a-z_-]+$/; expect(tool.name).toMatch(namePattern); @@ -112,7 +112,7 @@ describe('MCP Tools', () => { }); it('Should have valid scope patterns when scope is defined', () => { - const toolsWithScope = MakeMCPTools.filter(tool => tool.scope !== undefined); + const toolsWithScope = MakeTools.filter(tool => tool.scope !== undefined); expect(toolsWithScope.length).toBeGreaterThan(0); toolsWithScope.forEach(tool => { @@ -123,7 +123,7 @@ describe('MCP Tools', () => { }); it('Should have consistent execute function signatures', () => { - MakeMCPTools.forEach(tool => { + MakeTools.forEach(tool => { // Execute function should take Make instance as first parameter expect(tool.execute.length).toBeGreaterThanOrEqual(1); expect(tool.execute.length).toBeLessThanOrEqual(2); @@ -132,4 +132,77 @@ describe('MCP Tools', () => { expect(tool.execute.constructor.name).toBe('AsyncFunction'); }); }); + + it('Should have resourceId pointing to an existing inputSchema property when set', () => { + const toolsWithResourceId = MakeTools.filter(tool => tool.resourceId !== undefined); + expect(toolsWithResourceId.length).toBeGreaterThan(0); + + toolsWithResourceId.forEach(tool => { + expect(typeof tool.resourceId).toBe('string'); + expect(tool.resourceId!.length).toBeGreaterThan(0); + + const properties = tool.inputSchema.properties ?? {}; + expect(properties).toHaveProperty(tool.resourceId!); + }); + }); + + it('Should have scopeId pointing to an existing inputSchema property when set', () => { + const toolsWithScopeId = MakeTools.filter(tool => tool.scopeId !== undefined); + expect(toolsWithScopeId.length).toBeGreaterThan(0); + + toolsWithScopeId.forEach(tool => { + expect(typeof tool.scopeId).toBe('string'); + expect(tool.scopeId!.length).toBeGreaterThan(0); + + const properties = tool.inputSchema.properties ?? {}; + expect(properties).toHaveProperty(tool.scopeId!); + }); + }); + + it('Should mirror scopeId and the deprecated identifier alias on every tool', () => { + MakeTools.forEach(tool => { + // Backward-compatibility invariant: when both are set they MUST agree; + // tools that set one MUST set the other (undefined counts as "set to undefined"). + expect(tool.scopeId).toBe(tool.identifier); + }); + }); + + it('Should have scopeId/resourceId set for key single-resource actions', () => { + const getByName = (name: string) => MakeTools.find(tool => tool.name === name); + + const executionsGet = getByName('executions_get'); + expect(executionsGet).toBeDefined(); + expect(executionsGet?.scopeId).toBe('scenarioId'); + expect(executionsGet?.identifier).toBe('scenarioId'); + expect(executionsGet?.resourceId).toBe('executionId'); + + const executionsGetDetail = getByName('executions_get-detail'); + expect(executionsGetDetail).toBeDefined(); + expect(executionsGetDetail?.scopeId).toBe('scenarioId'); + expect(executionsGetDetail?.identifier).toBe('scenarioId'); + expect(executionsGetDetail?.resourceId).toBe('executionId'); + + const credentialRequestsGet = getByName('credential-requests_get'); + expect(credentialRequestsGet).toBeDefined(); + expect(credentialRequestsGet?.scopeId).toBe('requestId'); + expect(credentialRequestsGet?.resourceId).toBe('requestId'); + }); + + it('Should leave resourceId undefined for collection-level and composite-key tools', () => { + const collectionSuffixes = ['_list', '_create']; + const collectionTools = MakeTools.filter(tool => collectionSuffixes.some(suffix => tool.name.endsWith(suffix))); + expect(collectionTools.length).toBeGreaterThan(0); + + collectionTools.forEach(tool => { + expect(tool.resourceId).toBeUndefined(); + }); + + // sdk-* tools are keyed by composite names (app name + version, etc.) + // and should not declare a single primary resourceId. + const sdkTools = MakeTools.filter(tool => tool.category.startsWith('sdk-')); + expect(sdkTools.length).toBeGreaterThan(0); + sdkTools.forEach(tool => { + expect(tool.resourceId).toBeUndefined(); + }); + }); }); diff --git a/tsup.config.ts b/tsup.config.ts index 75583ff..643ece1 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -1,7 +1,7 @@ import { defineConfig } from 'tsup'; export default defineConfig({ - entryPoints: ['src/index.ts', 'src/mcp.ts'], + entryPoints: ['src/index.ts', 'src/tools.ts', 'src/mcp.ts'], format: ['cjs', 'esm'], dts: true, outDir: 'dist',