├── .nvmrc ├── examples ├── production-example │ ├── file.ts │ └── README.md ├── runtime-openapi-loading │ ├── package.json │ └── server.ts ├── utils │ ├── package.json │ └── index.ts ├── langchain-react-agent │ ├── env.example │ ├── package.json │ └── simple-test.ts ├── quickstart │ ├── package.json │ ├── README.md │ ├── server.ts │ └── index.ts ├── google-calendar-agent │ ├── .gitignore │ ├── env.example │ ├── package.json │ ├── auth │ │ └── README.md │ └── mcp │ │ └── README.md ├── vercel-ai-sdk-example │ ├── server.ts │ ├── package.json │ ├── streaming.ts │ └── agent.ts ├── simple-code-agent │ ├── package.json │ └── README.md ├── langchain-quickstart │ ├── package.json │ ├── README.md │ └── index.ts ├── client-tools │ ├── package.json │ └── server.ts ├── oauth-example │ └── package.json ├── framework-integration │ ├── package.json │ └── express-example.ts ├── monday-graphql │ ├── show-queries.sh │ ├── package.json │ └── agent.ts ├── opentelemetry │ └── package.json ├── openapi-example │ └── server.ts ├── streaming-events │ ├── package.json │ └── simple-test.ts ├── token-refresh │ └── README.md └── test-server │ ├── server.ts │ └── README.md ├── .husky └── pre-commit ├── commitlint.config.ts ├── packages ├── server │ ├── src │ │ ├── security │ │ │ └── index.ts │ │ ├── executor │ │ │ ├── index.ts │ │ │ ├── constants.ts │ │ │ ├── types.ts │ │ │ └── resume-handler.ts │ │ ├── instrumentation │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── controllers │ │ │ ├── info.controller.ts │ │ │ ├── search.controller.ts │ │ │ └── definitions.controller.ts │ │ ├── utils │ │ │ ├── runtime-types.ts │ │ │ ├── schema.ts │ │ │ ├── index.ts │ │ │ ├── info.ts │ │ │ ├── error.ts │ │ │ ├── banner.ts │ │ │ ├── request.ts │ │ │ ├── response.ts │ │ │ └── context.ts │ │ ├── handlers │ │ │ ├── explorer.handler.ts │ │ │ ├── definitions.handler.ts │ │ │ ├── search.handler.ts │ │ │ └── init.handler.ts │ │ ├── core │ │ │ └── http.ts │ │ ├── http │ │ │ └── router.ts │ │ └── index.ts │ ├── tsup.config.ts │ ├── project.json │ └── tsconfig.json ├── providers │ ├── src │ │ ├── oauth │ │ │ └── index.ts │ │ ├── index.ts │ │ └── auth │ │ │ └── env.ts │ ├── tsconfig.json │ ├── tsup.config.ts │ ├── project.json │ └── package.json ├── runtime │ ├── src │ │ ├── progress │ │ │ ├── types.ts │ │ │ └── index.ts │ │ ├── cache │ │ │ ├── types.ts │ │ │ └── index.ts │ │ ├── approval │ │ │ ├── types.ts │ │ │ └── handler.ts │ │ ├── log │ │ │ └── types.ts │ │ ├── metadata │ │ │ ├── types.ts │ │ │ └── decorators.ts │ │ ├── registry.ts │ │ ├── embedding │ │ │ ├── types.ts │ │ │ └── utils.ts │ │ ├── pause │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── llm │ │ │ ├── callback.ts │ │ │ └── types.ts │ │ ├── utils.ts │ │ └── index.ts │ ├── tsup.config.ts │ ├── tsconfig.json │ ├── project.json │ └── package.json ├── client │ ├── src │ │ ├── tools │ │ │ ├── index.ts │ │ │ ├── types.ts │ │ │ ├── fetch-all-apis.ts │ │ │ ├── search-api.ts │ │ │ └── explore-api.ts │ │ ├── core │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── generator.ts │ │ ├── tools.ts │ │ ├── index.ts │ │ └── errors.ts │ ├── tsup.config.ts │ ├── project.json │ ├── tsconfig.json │ └── package.json ├── protocol │ ├── src │ │ ├── index.ts │ │ ├── schemas.ts │ │ └── oauth.ts │ ├── tsconfig.json │ ├── tsup.config.ts │ ├── project.json │ └── package.json ├── provenance │ ├── tsup.config.ts │ ├── tsconfig.json │ ├── project.json │ ├── package.json │ └── src │ │ ├── policies │ │ ├── schema.ts │ │ └── builder.ts │ │ ├── index.ts │ │ └── __tests__ │ │ └── dynamic-policy.test.ts ├── atp-compiler │ ├── tsup.config.ts │ ├── src │ │ ├── plugin-system │ │ │ ├── default-plugins │ │ │ │ ├── index.ts │ │ │ │ ├── detection-plugin.ts │ │ │ │ ├── loop-transformer-plugin.ts │ │ │ │ ├── array-transformer-plugin.ts │ │ │ │ └── promise-transformer-plugin.ts │ │ │ ├── index.ts │ │ │ └── create-default-compiler.ts │ │ ├── runtime │ │ │ ├── batch-parallel.ts │ │ │ ├── context.ts │ │ │ ├── index.ts │ │ │ ├── resumable-parallel.ts │ │ │ └── runtime-functions.ts │ │ ├── index.ts │ │ ├── transformer │ │ │ ├── array-transformer-sequential.ts │ │ │ └── array-transformer-utils.ts │ │ └── types │ │ │ └── compiler-interface.ts │ ├── tsconfig.json │ ├── jest.config.js │ ├── project.json │ └── package.json ├── mcp-adapter │ ├── tsup.config.ts │ ├── src │ │ ├── types.ts │ │ ├── index.ts │ │ └── schema-utils.ts │ ├── project.json │ ├── tsconfig.json │ └── package.json ├── vercel-ai-sdk │ ├── tsup.config.ts │ ├── tsconfig.json │ ├── src │ │ └── index.ts │ ├── project.json │ ├── jest.config.cjs │ └── package.json └── langchain │ ├── tsup.config.ts │ ├── src │ ├── index.ts │ ├── node.ts │ └── tools.ts │ ├── project.json │ ├── tsconfig.json │ └── package.json ├── .yarnrc.yml ├── .prettierrc ├── .prettierrc.json ├── .prettierignore ├── __mocks__ └── zod-to-json-schema │ └── index.js ├── __tests__ ├── e2e │ └── test-config.ts ├── setup.ts └── README.md ├── .gitignore ├── jest.e2e.config.ts ├── LICENSE ├── env.example ├── tsconfig.json ├── nx.json ├── .github └── workflows │ ├── test.yml │ ├── version-atp.yml │ └── publish-atp.yml └── jest.config.js /.nvmrc: -------------------------------------------------------------------------------- 1 | 22 2 | -------------------------------------------------------------------------------- /examples/production-example/file.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | npx --no -- commitlint --edit $1 -------------------------------------------------------------------------------- /commitlint.config.ts: -------------------------------------------------------------------------------- 1 | export default { extends: ['@commitlint/config-conventional'] }; 2 | -------------------------------------------------------------------------------- /packages/server/src/security/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@mondaydotcomorg/atp-provenance'; 2 | -------------------------------------------------------------------------------- /packages/providers/src/oauth/index.ts: -------------------------------------------------------------------------------- 1 | export { ScopeCheckerRegistry } from './scope-checkers.js'; 2 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | 3 | enableGlobalCache: true 4 | 5 | npmRegistryServer: 'https://registry.npmjs.org/' 6 | 7 | yarnPath: .yarn/releases/yarn-4.5.1.cjs 8 | -------------------------------------------------------------------------------- /packages/runtime/src/progress/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | /** 4 | * Progress callback function type 5 | */ 6 | export type ProgressCallback = (message: string, fraction: number) => void; 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "trailingComma": "es5", 4 | "singleQuote": true, 5 | "printWidth": 100, 6 | "tabWidth": 2, 7 | "useTabs": true, 8 | "arrowParens": "always" 9 | } 10 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "trailingComma": "es5", 4 | "singleQuote": true, 5 | "printWidth": 100, 6 | "tabWidth": 2, 7 | "useTabs": true, 8 | "arrowParens": "avoid" 9 | } 10 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | build 4 | coverage 5 | .next 6 | *.log 7 | .DS_Store 8 | *.tsbuildinfo 9 | .yarn 10 | .pnp.* 11 | yarn.lock 12 | package-lock.json 13 | pnpm-lock.yaml 14 | 15 | -------------------------------------------------------------------------------- /packages/server/src/executor/index.ts: -------------------------------------------------------------------------------- 1 | export { SandboxExecutor } from './executor.js'; 2 | export type { RuntimeContext, ExecutorConfig } from './types.js'; 3 | export { categorizeError } from './error-handler.js'; 4 | -------------------------------------------------------------------------------- /packages/client/src/tools/index.ts: -------------------------------------------------------------------------------- 1 | export * from './types.js'; 2 | export * from './search-api.js'; 3 | export * from './fetch-all-apis.js'; 4 | export * from './execute-code.js'; 5 | export * from './explore-api.js'; 6 | -------------------------------------------------------------------------------- /packages/server/src/instrumentation/index.ts: -------------------------------------------------------------------------------- 1 | export { CodeInstrumentor } from './transformer.js'; 2 | export { StateManager } from './state-manager.js'; 3 | export { Serializer } from './serializer.js'; 4 | export * from './types.js'; 5 | -------------------------------------------------------------------------------- /examples/runtime-openapi-loading/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@examples/runtime-openapi-loading", 3 | "version": "1.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "tsx server.ts" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@examples/utils", 3 | "version": "1.0.0", 4 | "private": true, 5 | "type": "module", 6 | "main": "index.ts", 7 | "types": "index.ts", 8 | "exports": { 9 | ".": "./index.ts" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/protocol/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './types.js'; 2 | export * from './schemas.js'; 3 | export * from './validation.js'; 4 | export * from './auth.js'; 5 | export * from './providers.js'; 6 | export * from './oauth.js'; 7 | export * from './events.js'; 8 | -------------------------------------------------------------------------------- /packages/server/src/executor/constants.ts: -------------------------------------------------------------------------------- 1 | export const PAUSE_EXECUTION_MARKER = '__PAUSE_EXECUTION__'; 2 | 3 | export const ATP_COMPILER_ENABLED = true; 4 | 5 | export const ATP_BATCH_SIZE_THRESHOLD = parseInt(process.env.ATP_BATCH_SIZE_THRESHOLD || '10', 10); 6 | -------------------------------------------------------------------------------- /packages/runtime/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts'], 5 | format: ['esm', 'cjs'], 6 | dts: false, 7 | sourcemap: true, 8 | clean: false, 9 | splitting: false, 10 | treeshake: true, 11 | }); 12 | -------------------------------------------------------------------------------- /__mocks__/zod-to-json-schema/index.js: -------------------------------------------------------------------------------- 1 | // Mock zod-to-json-schema for Jest 2 | module.exports = { 3 | zodToJsonSchema: (schema) => { 4 | // Simple mock that returns a basic JSON schema 5 | return { 6 | type: 'object', 7 | properties: {}, 8 | required: [], 9 | }; 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /packages/protocol/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist", 6 | "composite": true 7 | }, 8 | "include": ["src/**/*"], 9 | "exclude": ["node_modules", "dist", "**/*.test.ts"], 10 | "references": [{ "path": "../provenance" }] 11 | } 12 | -------------------------------------------------------------------------------- /examples/langchain-react-agent/env.example: -------------------------------------------------------------------------------- 1 | # Example environment configuration 2 | # Copy this to .env and fill in your values 3 | 4 | # OpenAI API Key for LLM calls 5 | OPENAI_API_KEY=sk-proj-your-openai-api-key-here 6 | 7 | # ATP Server Configuration (optional, defaults shown) 8 | ATP_SERVER_URL=http://localhost:3333 9 | ATP_API_KEY=test-key 10 | 11 | -------------------------------------------------------------------------------- /packages/runtime/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist", 6 | "composite": true, 7 | "experimentalDecorators": true, 8 | "emitDecoratorMetadata": true 9 | }, 10 | "include": ["src/**/*"], 11 | "exclude": ["node_modules", "dist", "**/*.test.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /packages/protocol/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts'], 5 | format: ['esm', 'cjs'], 6 | dts: false, 7 | sourcemap: true, 8 | clean: false, 9 | splitting: false, 10 | treeshake: true, 11 | external: [ 12 | 'zod', 13 | '@mondaydotcomorg/atp-provenance', 14 | ], 15 | }); 16 | -------------------------------------------------------------------------------- /packages/provenance/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts'], 5 | format: ['esm', 'cjs'], 6 | dts: false, 7 | sourcemap: true, 8 | clean: false, 9 | splitting: false, 10 | treeshake: true, 11 | external: [ 12 | 'zod', 13 | '@mondaydotcomorg/atp-runtime', 14 | ], 15 | }); 16 | -------------------------------------------------------------------------------- /packages/atp-compiler/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts'], 5 | format: ['esm', 'cjs'], 6 | dts: false, 7 | sourcemap: true, 8 | clean: false, 9 | splitting: false, 10 | treeshake: true, 11 | external: [ 12 | '@mondaydotcomorg/atp-protocol', 13 | '@mondaydotcomorg/atp-runtime', 14 | ], 15 | }); 16 | 17 | -------------------------------------------------------------------------------- /packages/client/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts', 'src/core/index.ts'], 5 | format: ['esm', 'cjs'], 6 | dts: false, 7 | sourcemap: true, 8 | clean: false, 9 | splitting: false, 10 | treeshake: true, 11 | external: [ 12 | 'zod', 13 | '@mondaydotcomorg/atp-protocol', 14 | '@mondaydotcomorg/atp-runtime', 15 | ], 16 | }); 17 | -------------------------------------------------------------------------------- /packages/providers/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "declaration": true, 7 | "declarationMap": true, 8 | "sourceMap": true, 9 | "composite": true 10 | }, 11 | "include": ["src/**/*"], 12 | "exclude": ["dist", "node_modules"], 13 | "references": [{ "path": "../protocol" }, { "path": "../runtime" }] 14 | } 15 | -------------------------------------------------------------------------------- /packages/providers/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts'], 5 | format: ['esm', 'cjs'], 6 | dts: false, 7 | sourcemap: true, 8 | clean: false, 9 | splitting: false, 10 | treeshake: true, 11 | external: [ 12 | '@mondaydotcomorg/atp-protocol', 13 | '@mondaydotcomorg/atp-runtime', 14 | '@opentelemetry/api', 15 | ], 16 | }); 17 | 18 | -------------------------------------------------------------------------------- /packages/provenance/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "composite": true, 7 | "declaration": true, 8 | "declarationMap": true, 9 | "sourceMap": true 10 | }, 11 | "include": ["src/**/*.ts"], 12 | "exclude": ["node_modules", "dist", "**/__tests__", "**/*.test.ts", "**/*.spec.ts"], 13 | "references": [{ "path": "../runtime" }] 14 | } 15 | -------------------------------------------------------------------------------- /packages/atp-compiler/src/plugin-system/default-plugins/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Default Plugins 3 | * 4 | * These plugins wrap the existing ATP Compiler functionality, 5 | * making the PluggableCompiler a drop-in replacement for ATPCompiler. 6 | */ 7 | 8 | export * from './detection-plugin.js'; 9 | export * from './loop-transformer-plugin.js'; 10 | export * from './array-transformer-plugin.js'; 11 | export * from './promise-transformer-plugin.js'; 12 | -------------------------------------------------------------------------------- /examples/quickstart/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "quickstart-example", 3 | "version": "1.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "start": "NODE_OPTIONS='--no-node-snapshot' tsx index.ts" 8 | }, 9 | "dependencies": { 10 | "@mondaydotcomorg/atp-client": "workspace:*", 11 | "@mondaydotcomorg/atp-mcp-adapter": "workspace:*", 12 | "@mondaydotcomorg/atp-server": "workspace:*", 13 | "tsx": "^4.19.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/server/src/controllers/info.controller.ts: -------------------------------------------------------------------------------- 1 | import type { IncomingMessage, ServerResponse } from 'node:http'; 2 | import { sendJson } from '../utils/response.js'; 3 | 4 | export async function handleInfo(req: IncomingMessage, res: ServerResponse): Promise { 5 | sendJson(res, { 6 | version: '1.0.0', 7 | capabilities: { 8 | execution: true, 9 | search: true, 10 | streaming: true, 11 | llmCalls: true, 12 | }, 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /packages/mcp-adapter/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts'], 5 | format: ['esm', 'cjs'], 6 | dts: false, // Use tsc for declarations due to project references 7 | sourcemap: true, 8 | clean: false, 9 | splitting: false, 10 | treeshake: true, 11 | external: [ 12 | 'zod', 13 | '@mondaydotcomorg/atp-protocol', 14 | '@mondaydotcomorg/atp-server', 15 | ], 16 | }); 17 | 18 | -------------------------------------------------------------------------------- /packages/vercel-ai-sdk/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts'], 5 | format: ['esm', 'cjs'], 6 | dts: false, // Use tsc for declarations due to project references 7 | sourcemap: true, 8 | clean: false, 9 | splitting: false, 10 | treeshake: true, 11 | external: [ 12 | 'zod', 13 | 'ai', 14 | '@mondaydotcomorg/atp-client', 15 | '@mondaydotcomorg/atp-protocol', 16 | ], 17 | }); 18 | 19 | -------------------------------------------------------------------------------- /packages/mcp-adapter/src/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Shared types for MCP Adapter 3 | */ 4 | 5 | export interface MCPTool { 6 | name: string; 7 | description?: string; 8 | inputSchema: { 9 | type: string; 10 | properties?: Record; 11 | required?: string[]; 12 | }; 13 | } 14 | 15 | export interface MCPPrompt { 16 | name: string; 17 | description?: string; 18 | arguments?: Array<{ 19 | name: string; 20 | description?: string; 21 | required?: boolean; 22 | }>; 23 | } 24 | -------------------------------------------------------------------------------- /packages/mcp-adapter/src/index.ts: -------------------------------------------------------------------------------- 1 | export { MCPConnector } from './mcp-connector.js'; 2 | export { MCPHttpConnector } from './http-connector.js'; 3 | export { registerATPTools, registerToolsWithMCP } from './atp-to-mcp.js'; 4 | export { convertMCPInputSchema, convertMCPToolToFunction } from './schema-utils.js'; 5 | export type { MCPTool, MCPPrompt } from './types.js'; 6 | export type { MCPToolResult, MCPServerLike } from './atp-to-mcp.js'; 7 | export type { MCPToolSchema, MCPToolDefinition } from './schema-utils.js'; 8 | -------------------------------------------------------------------------------- /packages/client/src/core/index.ts: -------------------------------------------------------------------------------- 1 | export * from './session.js'; 2 | export * from './in-process-session.js'; 3 | export * from './api-operations.js'; 4 | export * from './execution-operations.js'; 5 | export * from './service-providers.js'; 6 | export * from './types.js'; 7 | 8 | export { CallbackType } from '@mondaydotcomorg/atp-protocol'; 9 | export type { 10 | ClientLLMHandler, 11 | ClientApprovalHandler, 12 | ClientEmbeddingHandler, 13 | ClientServiceProviders, 14 | } from '@mondaydotcomorg/atp-protocol'; 15 | -------------------------------------------------------------------------------- /packages/server/src/utils/runtime-types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Runtime SDK Type Generator 3 | * 4 | * Generates TypeScript definitions from the runtime API registry. 5 | */ 6 | import { GENERATED_METADATA, generateRuntimeTypes as generate } from '@mondaydotcomorg/atp-runtime'; 7 | 8 | /** 9 | * Generates TypeScript definitions for the runtime SDK 10 | * Delegates to the runtime package's own type generator 11 | */ 12 | export function generateRuntimeTypes(): string { 13 | return generate(GENERATED_METADATA); 14 | } 15 | -------------------------------------------------------------------------------- /examples/google-calendar-agent/.gitignore: -------------------------------------------------------------------------------- 1 | # Environment variables 2 | .env 3 | 4 | # Node modules 5 | node_modules/ 6 | 7 | # Build output 8 | dist/ 9 | build/ 10 | 11 | # OAuth tokens 12 | token.json 13 | tokens/ 14 | 15 | # Logs 16 | *.log 17 | server.log 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | 22 | # IDE 23 | .vscode/ 24 | .idea/ 25 | *.swp 26 | *.swo 27 | 28 | # OS 29 | .DS_Store 30 | Thumbs.db 31 | 32 | # Credentials (keep these secure!) 33 | gcp-oauth.keys.json 34 | credentials.json 35 | 36 | -------------------------------------------------------------------------------- /packages/atp-compiler/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "declaration": true, 7 | "declarationMap": true, 8 | "sourceMap": true, 9 | "skipLibCheck": true, 10 | "composite": true 11 | }, 12 | "include": ["src/**/*.ts"], 13 | "exclude": ["node_modules", "dist", "**/__tests__", "**/*.test.ts", "**/*.spec.ts"], 14 | "references": [{ "path": "../protocol" }, { "path": "../provenance" }, { "path": "../runtime" }] 15 | } 16 | -------------------------------------------------------------------------------- /examples/vercel-ai-sdk-example/server.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from '@mondaydotcomorg/atp-server'; 2 | 3 | const server = createServer(); 4 | 5 | server.tool('example', { 6 | description: 'Example tool', 7 | input: { message: 'string' }, 8 | handler: async (input: unknown) => { 9 | const { message } = input as { message: string }; 10 | return `Received: ${message}`; 11 | }, 12 | }); 13 | 14 | await server.listen(3333); 15 | console.log('✅ ATP Server running on http://localhost:3333'); 16 | console.log(' API Key: test-key'); 17 | -------------------------------------------------------------------------------- /packages/langchain/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts'], 5 | format: ['esm', 'cjs'], 6 | dts: false, // Use tsc for declarations due to project references 7 | sourcemap: true, 8 | clean: false, 9 | splitting: false, 10 | treeshake: true, 11 | external: [ 12 | 'zod', 13 | '@langchain/core', 14 | 'langchain', 15 | '@mondaydotcomorg/atp-client', 16 | '@mondaydotcomorg/atp-protocol', 17 | '@mondaydotcomorg/atp-runtime', 18 | ], 19 | }); 20 | 21 | -------------------------------------------------------------------------------- /packages/server/src/utils/schema.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Converts a simple type map to a JSON Schema object 3 | */ 4 | export function toJSONSchema(types: Record): { 5 | type: 'object'; 6 | properties: Record; 7 | required: string[]; 8 | } { 9 | const properties: Record = {}; 10 | const required: string[] = []; 11 | 12 | for (const [key, type] of Object.entries(types)) { 13 | properties[key] = { type }; 14 | required.push(key); 15 | } 16 | 17 | return { type: 'object', properties, required }; 18 | } 19 | -------------------------------------------------------------------------------- /packages/langchain/src/index.ts: -------------------------------------------------------------------------------- 1 | export { createATPTools as createATPToolsBasic, convertToLangChainTools } from './tools.js'; 2 | 3 | export * from './langgraph-client.js'; 4 | export { 5 | createATPTools, 6 | createSimpleATPTool, 7 | type CreateATPToolsOptions, 8 | type ATPToolsResult, 9 | } from './langgraph-tools.js'; 10 | 11 | export { 12 | createLangChainEventHandler, 13 | createCallbackManagerHandler, 14 | type LangChainEvent, 15 | type CreateLangChainEventHandlerOptions, 16 | } from './event-adapter.js'; 17 | 18 | export * from './node.js'; 19 | -------------------------------------------------------------------------------- /packages/atp-compiler/src/plugin-system/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * check 3 | * 4 | * ATP Compiler Plugin System 5 | * 6 | * Extensible plugin architecture for custom transformations 7 | */ 8 | 9 | export * from './plugin-api.js'; 10 | export * from './pluggable-compiler.js'; 11 | export * from './create-default-compiler.js'; 12 | 13 | // Default plugins 14 | export * from './default-plugins/index.js'; 15 | 16 | // Re-export examples for convenience 17 | export * from './examples/timeout-plugin.js'; 18 | export * from './examples/security-validator-plugin.js'; 19 | -------------------------------------------------------------------------------- /packages/runtime/src/cache/types.ts: -------------------------------------------------------------------------------- 1 | export interface CacheConfig { 2 | type: 'memory' | 'redis'; 3 | redis?: { 4 | host: string; 5 | port: number; 6 | password?: string; 7 | db?: number; 8 | }; 9 | maxKeys?: number; 10 | defaultTTL?: number; 11 | checkPeriod?: number; 12 | } 13 | 14 | export interface CacheBackend { 15 | get(key: string): Promise; 16 | set(key: string, value: unknown, ttl?: number): Promise; 17 | delete(key: string): Promise; 18 | has(key: string): Promise; 19 | clear(): Promise; 20 | } 21 | -------------------------------------------------------------------------------- /packages/server/src/handlers/explorer.handler.ts: -------------------------------------------------------------------------------- 1 | import type { RequestContext } from '../core/config.js'; 2 | import type { ExplorerService } from '../explorer/index.js'; 3 | 4 | export async function handleExplore( 5 | ctx: RequestContext, 6 | explorerService: ExplorerService 7 | ): Promise { 8 | const body = ctx.body as { path?: string }; 9 | const path = body.path || '/'; 10 | 11 | const result = explorerService.explore(path); 12 | 13 | if (!result) { 14 | ctx.throw(404, `Path not found: ${path}`); 15 | } 16 | 17 | return result; 18 | } 19 | -------------------------------------------------------------------------------- /examples/simple-code-agent/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "simple-code-agent", 3 | "version": "1.0.0", 4 | "private": true, 5 | "description": "Simple example using ATP chat utilities", 6 | "main": "simple-agent.ts", 7 | "scripts": { 8 | "start": "NODE_OPTIONS='--no-node-snapshot' tsx simple-agent.ts" 9 | }, 10 | "dependencies": { 11 | "@langchain/core": "^0.2.0", 12 | "@langchain/langgraph": "^0.0.19", 13 | "@langchain/openai": "^0.1.0", 14 | "@mondaydotcomorg/atp-langchain": "workspace:*", 15 | "dotenv": "^16.4.5", 16 | "tsx": "^4.7.2" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/server/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts'], 5 | format: ['esm', 'cjs'], 6 | dts: false, // Use tsc for declarations due to project references 7 | sourcemap: true, 8 | clean: false, 9 | splitting: false, 10 | treeshake: true, 11 | external: [ 12 | '@mondaydotcomorg/atp-protocol', 13 | '@mondaydotcomorg/atp-provenance', 14 | '@mondaydotcomorg/atp-providers', 15 | '@mondaydotcomorg/atp-runtime', 16 | '@mondaydotcomorg/atp-compiler', 17 | 'isolated-vm', 18 | ], 19 | }); 20 | -------------------------------------------------------------------------------- /packages/vercel-ai-sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "composite": true, 7 | "declaration": true, 8 | "declarationMap": true, 9 | "sourceMap": true, 10 | "module": "ESNext", 11 | "moduleResolution": "bundler", 12 | "target": "ES2022", 13 | "lib": ["ES2022"], 14 | "skipLibCheck": true 15 | }, 16 | "include": ["src/**/*"], 17 | "exclude": ["node_modules", "dist", "__tests__"], 18 | "references": [{ "path": "../client" }, { "path": "../protocol" }] 19 | } 20 | -------------------------------------------------------------------------------- /examples/langchain-quickstart/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "langchain-quickstart-example", 3 | "version": "1.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "start": "NODE_OPTIONS='--no-node-snapshot' tsx index.ts" 8 | }, 9 | "dependencies": { 10 | "@langchain/core": "^0.3.22", 11 | "@langchain/langgraph": "^0.2.28", 12 | "@langchain/openai": "^0.3.17", 13 | "@mondaydotcomorg/atp-client": "workspace:*", 14 | "@mondaydotcomorg/atp-langchain": "workspace:*", 15 | "@mondaydotcomorg/atp-server": "workspace:*", 16 | "tsx": "^4.19.2" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/runtime/src/approval/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Human Approval API Types 3 | */ 4 | 5 | export interface ApprovalRequest { 6 | message: string; 7 | context?: Record; 8 | timeout?: number; 9 | schema?: ApprovalSchema; 10 | } 11 | 12 | export interface ApprovalSchema { 13 | type: 'boolean' | 'text' | 'choice' | 'structured'; 14 | choices?: string[]; 15 | structuredSchema?: Record; 16 | required?: boolean; 17 | } 18 | 19 | export interface ApprovalResponse { 20 | approved: boolean; 21 | response?: T; 22 | timestamp: number; 23 | } 24 | -------------------------------------------------------------------------------- /examples/client-tools/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "atp-client-tools-example", 3 | "version": "1.0.0", 4 | "private": true, 5 | "description": "Example of client-provided tools in Agent Tool Protocol", 6 | "type": "module", 7 | "scripts": { 8 | "server": "tsx server.ts", 9 | "client": "tsx client.ts" 10 | }, 11 | "dependencies": { 12 | "@mondaydotcomorg/atp-client": "workspace:*", 13 | "@mondaydotcomorg/atp-protocol": "workspace:*", 14 | "@mondaydotcomorg/atp-server": "workspace:*" 15 | }, 16 | "devDependencies": { 17 | "tsx": "^4.7.0", 18 | "typescript": "^5.3.3" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/client/src/generator.ts: -------------------------------------------------------------------------------- 1 | import { AgentToolProtocolClient } from './client.js'; 2 | import { log } from '@mondaydotcomorg/atp-runtime'; 3 | 4 | export class CodeGenerator { 5 | private client: AgentToolProtocolClient; 6 | 7 | constructor(client: AgentToolProtocolClient) { 8 | this.client = client; 9 | } 10 | 11 | async generateCode(intent: string, parameters?: unknown): Promise { 12 | const types = this.client.getTypeDefinitions(); 13 | log.debug('Generating code for intent', { intent, parameters, typesLength: types.length }); 14 | return '// Generated code'; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/server/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export { toJSONSchema } from './schema.js'; 2 | export { printBanner, type BannerOptions } from './banner.js'; 3 | export { handleError } from './error.js'; 4 | export { createContext, type CreateContextOptions } from './context.js'; 5 | export { getServerInfo, type ServerInfo, type ServerLimits } from './info.js'; 6 | export { readBody, readJsonBody, DEFAULT_MAX_BODY_SIZE } from './request.js'; 7 | export { 8 | sendJson, 9 | sendError, 10 | send404, 11 | sendBadRequest, 12 | sendServiceUnavailable, 13 | setCorsHeaders, 14 | handleOptions, 15 | } from './response.js'; 16 | -------------------------------------------------------------------------------- /packages/vercel-ai-sdk/src/index.ts: -------------------------------------------------------------------------------- 1 | export { VercelAIATPClient } from './client.js'; 2 | export { createATPTools, createATPStreamingTools } from './tools.js'; 3 | export { 4 | createVercelEventHandler, 5 | createEventCollector, 6 | type UIMessageStreamWriter, 7 | type UIStreamEvent, 8 | type CreateVercelEventHandlerOptions, 9 | } from './event-adapter.js'; 10 | export type { 11 | VercelAIATPClientOptions, 12 | CreateATPToolsOptions, 13 | StreamingToolsOptions, 14 | ATPToolsResult, 15 | ApprovalHandler, 16 | ApprovalRequest, 17 | ApprovalResponse, 18 | EmbeddingProvider, 19 | } from './types.js'; 20 | -------------------------------------------------------------------------------- /examples/utils/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ATP Chat Utilities 3 | * 4 | * Generic utilities for building interactive chat agents with ATP code execution 5 | */ 6 | 7 | export { ChatFormatter, colors } from './chat-formatter.js'; 8 | export type { ChatFormatterOptions } from './chat-formatter.js'; 9 | export { CodeExecutionHandler } from './code-execution-handler.js'; 10 | export type { CodeExecutionState, AgentEvent, ToolCall, AgentMessage } from './code-execution-handler.js'; 11 | export { InteractiveChatRunner } from './interactive-chat-runner.js'; 12 | export type { InteractiveAgentConfig } from './interactive-chat-runner.js'; 13 | -------------------------------------------------------------------------------- /packages/server/src/controllers/search.controller.ts: -------------------------------------------------------------------------------- 1 | import type { IncomingMessage, ServerResponse } from 'node:http'; 2 | import type { SearchOptions } from '@mondaydotcomorg/atp-protocol'; 3 | import type { SearchEngine } from '../search/index.js'; 4 | import { sendJson } from '../utils/response.js'; 5 | 6 | export async function handleSearch( 7 | req: IncomingMessage, 8 | res: ServerResponse, 9 | searchEngine: SearchEngine, 10 | body: string 11 | ): Promise { 12 | const searchOptions = JSON.parse(body) as SearchOptions; 13 | const results = await searchEngine.search(searchOptions); 14 | 15 | sendJson(res, { results }); 16 | } 17 | -------------------------------------------------------------------------------- /packages/server/src/executor/types.ts: -------------------------------------------------------------------------------- 1 | import type { CacheProvider } from '@mondaydotcomorg/atp-protocol'; 2 | 3 | export interface RuntimeContext { 4 | llmCallCount: number; 5 | approvalCallCount: number; 6 | logs: string[]; 7 | startTime: number; 8 | maxLLMCalls: number; 9 | executionId: string; 10 | clientId?: string; 11 | hintMetadata?: Map; 12 | } 13 | 14 | export interface ExecutorConfig { 15 | defaultTimeout: number; 16 | maxTimeout: number; 17 | defaultMemoryLimit: number; 18 | maxMemoryLimit: number; 19 | defaultLLMCallLimit: number; 20 | maxLLMCallLimit: number; 21 | cacheProvider?: CacheProvider; 22 | } 23 | -------------------------------------------------------------------------------- /packages/runtime/src/log/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Log API Types 3 | */ 4 | 5 | export type LogLevel = 'none' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'; 6 | 7 | export interface LoggerConfig { 8 | level: LogLevel; 9 | pretty?: boolean; 10 | destination?: string; 11 | redact?: string[]; 12 | } 13 | 14 | export interface Logger { 15 | info(message: string, data?: unknown): void; 16 | warn(message: string, data?: unknown): void; 17 | error(message: string, data?: unknown): void; 18 | debug(message: string, data?: unknown): void; 19 | fatal(message: string, data?: unknown): void; 20 | child(bindings: Record): Logger; 21 | } 22 | -------------------------------------------------------------------------------- /packages/server/src/handlers/definitions.handler.ts: -------------------------------------------------------------------------------- 1 | import type { APIGroupConfig } from '@mondaydotcomorg/atp-protocol'; 2 | import { APIAggregator } from '../aggregator/index.js'; 3 | import { filterApiGroups } from '../core/request-scope.js'; 4 | 5 | export async function getDefinitions(apiGroups: APIGroupConfig[]): Promise { 6 | const filteredGroups = filterApiGroups(apiGroups); 7 | 8 | const aggregator = new APIAggregator(filteredGroups); 9 | const typescript = await aggregator.generateTypeScript(); 10 | 11 | return { 12 | typescript, 13 | apiGroups: filteredGroups.map((g) => g.name), 14 | version: '1.0.0', 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /examples/google-calendar-agent/env.example: -------------------------------------------------------------------------------- 1 | # OpenAI API Key (required for LangChain agent) 2 | OPENAI_API_KEY=your_openai_api_key_here 3 | 4 | # ATP Server Configuration 5 | ATP_SERVER_URL=http://localhost:3334 6 | ATP_AUTH_TOKEN=calendar-demo-token 7 | ATP_JWT_SECRET=your-jwt-secret-here-generate-with-openssl-rand-base64-32 8 | 9 | # Google OAuth Credentials 10 | # Download from Google Cloud Console -> APIs & Services -> Credentials 11 | # Create OAuth 2.0 Client ID -> Desktop App 12 | GOOGLE_OAUTH_CREDENTIALS=/path/to/your/gcp-oauth.keys.json 13 | 14 | # Optional: Custom token storage path 15 | # GOOGLE_CALENDAR_MCP_TOKEN_PATH=/path/to/token/storage 16 | 17 | -------------------------------------------------------------------------------- /packages/runtime/src/metadata/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Common metadata interface for runtime APIs 3 | * Each runtime module exports its metadata for the type generator 4 | */ 5 | 6 | import { RuntimeAPIName } from './generated'; 7 | 8 | export interface RuntimeAPIParam { 9 | name: string; 10 | type: string; 11 | description?: string; 12 | optional?: boolean; 13 | } 14 | 15 | export interface RuntimeAPIMethod { 16 | name: string; 17 | description: string; 18 | params: RuntimeAPIParam[]; 19 | returns: string; 20 | } 21 | 22 | export interface RuntimeAPIMetadata { 23 | name: RuntimeAPIName; 24 | description: string; 25 | methods: RuntimeAPIMethod[]; 26 | } 27 | -------------------------------------------------------------------------------- /packages/client/src/tools.ts: -------------------------------------------------------------------------------- 1 | import type { AgentToolProtocolClient } from './client.js'; 2 | import { 3 | type Tool, 4 | createSearchApiTool, 5 | createFetchAllApisTool, 6 | createExecuteCodeTool, 7 | createExploreApiTool, 8 | } from './tools/index.js'; 9 | 10 | /** 11 | * Creates MCP-compliant tool definitions with execution handlers 12 | * These tools work with any LLM/agent framework 13 | */ 14 | export function createToolsFromATPClient(client: AgentToolProtocolClient): Tool[] { 15 | return [ 16 | createSearchApiTool(client), 17 | createFetchAllApisTool(client), 18 | createExecuteCodeTool(client), 19 | createExploreApiTool(client), 20 | ]; 21 | } 22 | -------------------------------------------------------------------------------- /packages/runtime/src/registry.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Runtime API Registry 3 | * 4 | */ 5 | import type { RuntimeAPIMetadata } from './metadata/index.js'; 6 | import { GENERATED_METADATA } from './metadata/generated.js'; 7 | 8 | /** 9 | * Get all registered runtime APIs metadata 10 | * 11 | * This is generated at BUILD TIME by ts-morph, not at runtime 12 | */ 13 | export function getAllAPIs(): RuntimeAPIMetadata[] { 14 | return GENERATED_METADATA; 15 | } 16 | 17 | /** 18 | * Get metadata for a specific API by name 19 | */ 20 | export function getAPI(name: string): RuntimeAPIMetadata | undefined { 21 | return GENERATED_METADATA.find((api) => api.name === name); 22 | } 23 | -------------------------------------------------------------------------------- /__tests__/e2e/test-config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Centralized E2E Test Configuration 3 | * 4 | * Change the model here to affect all E2E tests 5 | */ 6 | 7 | export const TEST_CONFIG = { 8 | // Ollama model to use for all E2E tests 9 | // Options: 10 | // - 'gpt-oss:20b' - Larger, more capable model (slower, better reasoning) 11 | // - 'qwen2.5-coder:7b' - Smaller, faster model (faster, basic reasoning) 12 | ollamaModel: 'qwen2.5-coder:7b', 13 | 14 | // LLM temperature for deterministic results 15 | temperature: 0, 16 | 17 | // Agent configuration 18 | maxIterations: 15, 19 | 20 | // Test timeouts (in milliseconds) 21 | setupTimeout: 60000, 22 | testTimeout: 120000, 23 | }; 24 | -------------------------------------------------------------------------------- /packages/server/src/controllers/definitions.controller.ts: -------------------------------------------------------------------------------- 1 | import type { IncomingMessage, ServerResponse } from 'node:http'; 2 | import type { APIAggregator } from '../aggregator/index.js'; 3 | import { sendJson } from '../utils/response.js'; 4 | 5 | export async function handleDefinitions( 6 | req: IncomingMessage, 7 | res: ServerResponse, 8 | aggregator: APIAggregator, 9 | url: URL 10 | ): Promise { 11 | const apiGroups = url.searchParams.get('apiGroups')?.split(','); 12 | const typescript = await aggregator.generateTypeScript(apiGroups); 13 | 14 | sendJson(res, { 15 | typescript, 16 | apiGroups: aggregator.getApiGroups(), 17 | version: '1.0.0', 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /packages/server/src/core/http.ts: -------------------------------------------------------------------------------- 1 | import { IncomingMessage } from 'node:http'; 2 | import { readJsonBody } from '../utils/request.js'; 3 | 4 | export function parseBody(req: IncomingMessage): Promise { 5 | return readJsonBody(req); 6 | } 7 | 8 | export function parseQuery(url: string): Record { 9 | const queryIndex = url.indexOf('?'); 10 | if (queryIndex === -1) return {}; 11 | 12 | const queryString = url.substring(queryIndex + 1); 13 | const params = new URLSearchParams(queryString); 14 | const result: Record = {}; 15 | 16 | for (const [key, value] of params) { 17 | result[key] = value; 18 | } 19 | 20 | return result; 21 | } 22 | -------------------------------------------------------------------------------- /packages/client/src/tools/types.ts: -------------------------------------------------------------------------------- 1 | export const ToolNames = { 2 | SEARCH_API: 'search_api', 3 | FETCH_ALL_APIS: 'fetch_all_apis', 4 | EXECUTE_CODE: 'execute_code', 5 | EXPLORE_API: 'explore_api', 6 | } as const; 7 | 8 | export type ToolName = (typeof ToolNames)[keyof typeof ToolNames]; 9 | 10 | /** 11 | * Tool definition following MCP (Model Context Protocol) convention 12 | * with added execution function 13 | */ 14 | export interface Tool { 15 | name: string; 16 | description?: string; 17 | inputSchema: { 18 | type: string; 19 | properties?: Record; 20 | required?: string[]; 21 | }; 22 | zodSchema?: any; 23 | func: (input: TInput) => Promise; 24 | } 25 | -------------------------------------------------------------------------------- /packages/runtime/src/embedding/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Embedding API Types 3 | */ 4 | 5 | export interface EmbeddingOptions { 6 | input: string | string[]; 7 | model?: string; 8 | dimensions?: number; 9 | context?: Record; 10 | } 11 | 12 | export interface EmbeddingRecord { 13 | id: string; 14 | text: string; 15 | embedding: number[]; 16 | metadata?: Record; 17 | } 18 | 19 | export interface SearchOptions { 20 | query: string; 21 | topK?: number; 22 | minSimilarity?: number; 23 | filter?: Record; 24 | } 25 | 26 | export interface SearchResult { 27 | id: string; 28 | text: string; 29 | similarity: number; 30 | metadata?: Record; 31 | } 32 | -------------------------------------------------------------------------------- /examples/oauth-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "atp-oauth-example", 3 | "version": "1.0.0", 4 | "private": true, 5 | "description": "Complete OAuth flow example with user-scoped credentials for Agent Tool Protocol", 6 | "main": "server.ts", 7 | "scripts": { 8 | "dev": "tsx watch server.ts", 9 | "start": "tsx server.ts" 10 | }, 11 | "dependencies": { 12 | "@mondaydotcomorg/atp-protocol": "workspace:*", 13 | "@mondaydotcomorg/atp-providers": "workspace:*", 14 | "@mondaydotcomorg/atp-server": "workspace:*", 15 | "express": "^4.18.2" 16 | }, 17 | "devDependencies": { 18 | "@types/express": "^4.17.21", 19 | "@types/node": "^20.10.0", 20 | "tsx": "^4.7.0", 21 | "typescript": "^5.3.3" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/client/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-client", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "packages/client/src", 5 | "projectType": "library", 6 | "tags": ["atp-core"], 7 | "targets": { 8 | "build": { 9 | "executor": "nx:run-commands", 10 | "outputs": ["{projectRoot}/dist"], 11 | "options": { 12 | "command": "cd packages/client && npm run build" 13 | } 14 | }, 15 | "test": { 16 | "executor": "@nx/vite:test", 17 | "options": { 18 | "passWithNoTests": true 19 | } 20 | }, 21 | "lint": { 22 | "executor": "nx:run-commands", 23 | "options": { 24 | "command": "cd packages/client && npm run lint" 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/server/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-server", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "packages/server/src", 5 | "projectType": "library", 6 | "tags": ["atp-core"], 7 | "targets": { 8 | "build": { 9 | "executor": "nx:run-commands", 10 | "outputs": ["{projectRoot}/dist"], 11 | "options": { 12 | "command": "cd packages/server && npm run build" 13 | } 14 | }, 15 | "test": { 16 | "executor": "@nx/vite:test", 17 | "options": { 18 | "passWithNoTests": true 19 | } 20 | }, 21 | "lint": { 22 | "executor": "nx:run-commands", 23 | "options": { 24 | "command": "cd packages/server && npm run lint" 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/client-tools/server.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from '@mondaydotcomorg/atp-server'; 2 | 3 | /** 4 | * Basic ATP server for client tools example 5 | * No server-side tools needed - client will provide its own tools 6 | */ 7 | 8 | const server = createServer({ 9 | execution: { 10 | timeout: 30000, 11 | memory: 128 * 1024 * 1024, // 128 MB 12 | llmCalls: 10, 13 | }, 14 | logger: 'info', 15 | }); 16 | 17 | async function main() { 18 | await server.listen(3333); 19 | console.log('🚀 ATP Server running on http://localhost:3333'); 20 | console.log('📦 Client tools example - waiting for client connections...'); 21 | } 22 | 23 | main().catch((error) => { 24 | console.error('Server error:', error); 25 | process.exit(1); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/runtime/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-runtime", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "packages/runtime/src", 5 | "projectType": "library", 6 | "tags": ["atp-core"], 7 | "targets": { 8 | "build": { 9 | "executor": "nx:run-commands", 10 | "outputs": ["{projectRoot}/dist"], 11 | "options": { 12 | "command": "cd packages/runtime && npm run build" 13 | } 14 | }, 15 | "test": { 16 | "executor": "@nx/vite:test", 17 | "options": { 18 | "passWithNoTests": true 19 | } 20 | }, 21 | "lint": { 22 | "executor": "nx:run-commands", 23 | "options": { 24 | "command": "cd packages/runtime && npm run lint" 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/runtime/src/pause/index.ts: -------------------------------------------------------------------------------- 1 | import { PauseExecutionError, CallbackType } from './types.js'; 2 | 3 | export { 4 | PauseExecutionError, 5 | CallbackType, 6 | LLMOperation, 7 | EmbeddingOperation, 8 | ApprovalOperation, 9 | ToolOperation, 10 | } from './types.js'; 11 | 12 | /** 13 | * Helper to create pause error 14 | */ 15 | export function pauseForCallback( 16 | type: CallbackType, 17 | operation: string, 18 | payload: Record 19 | ): never { 20 | throw new PauseExecutionError(type, operation, payload); 21 | } 22 | 23 | /** 24 | * Check if error is a pause request 25 | */ 26 | export function isPauseError(error: unknown): error is PauseExecutionError { 27 | return error instanceof PauseExecutionError; 28 | } 29 | -------------------------------------------------------------------------------- /packages/runtime/src/llm/callback.ts: -------------------------------------------------------------------------------- 1 | /** 2 | */ 3 | import type { ClientLLMCallback } from './types'; 4 | 5 | /** 6 | * Client callback handler for LLM operations 7 | * When set, LLM calls will be routed to client instead of server LLM 8 | */ 9 | let clientLLMCallback: ClientLLMCallback | undefined; 10 | 11 | /** 12 | * Sets a client callback handler for LLM operations 13 | * @param callback - Client callback handler 14 | */ 15 | export function setClientLLMCallback(callback: ClientLLMCallback | undefined): void { 16 | clientLLMCallback = callback; 17 | } 18 | 19 | /** 20 | * Gets the current client callback handler 21 | */ 22 | export function getClientLLMCallback(): ClientLLMCallback | undefined { 23 | return clientLLMCallback; 24 | } 25 | -------------------------------------------------------------------------------- /packages/langchain/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-langchain", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "packages/langchain/src", 5 | "projectType": "library", 6 | "tags": ["atp-core"], 7 | "targets": { 8 | "build": { 9 | "executor": "nx:run-commands", 10 | "outputs": ["{projectRoot}/dist"], 11 | "options": { 12 | "command": "cd packages/langchain && npm run build" 13 | } 14 | }, 15 | "test": { 16 | "executor": "@nx/vite:test", 17 | "options": { 18 | "passWithNoTests": true 19 | } 20 | }, 21 | "lint": { 22 | "executor": "nx:run-commands", 23 | "options": { 24 | "command": "cd packages/langchain && npm run lint" 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/protocol/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-protocol", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "packages/protocol/src", 5 | "projectType": "library", 6 | "tags": ["atp-core"], 7 | "targets": { 8 | "build": { 9 | "executor": "nx:run-commands", 10 | "outputs": ["{projectRoot}/dist"], 11 | "options": { 12 | "command": "cd packages/protocol && npm run build" 13 | } 14 | }, 15 | "test": { 16 | "executor": "@nx/vite:test", 17 | "options": { 18 | "passWithNoTests": true 19 | } 20 | }, 21 | "lint": { 22 | "executor": "nx:run-commands", 23 | "options": { 24 | "command": "tsc -p packages/protocol/tsconfig.json --noEmit" 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/mcp-adapter/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-mcp-adapter", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "packages/mcp-adapter/src", 5 | "projectType": "library", 6 | "tags": ["atp-core"], 7 | "targets": { 8 | "build": { 9 | "executor": "nx:run-commands", 10 | "outputs": ["{projectRoot}/dist"], 11 | "options": { 12 | "command": "tsc --build packages/mcp-adapter/tsconfig.json" 13 | } 14 | }, 15 | "test": { 16 | "executor": "@nx/vite:test", 17 | "options": { 18 | "passWithNoTests": true 19 | } 20 | }, 21 | "lint": { 22 | "executor": "nx:run-commands", 23 | "options": { 24 | "command": "cd packages/mcp-adapter && npm run lint" 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/runtime/src/llm/types.ts: -------------------------------------------------------------------------------- 1 | export interface LLMCallOptions { 2 | prompt: string; 3 | context?: Record; 4 | model?: string; 5 | maxTokens?: number; 6 | temperature?: number; 7 | systemPrompt?: string; 8 | } 9 | 10 | export interface LLMExtractOptions { 11 | prompt: string; 12 | context?: Record; 13 | schema: unknown; 14 | } 15 | 16 | export interface LLMClassifyOptions { 17 | text: string; 18 | categories: string[]; 19 | context?: Record; 20 | } 21 | 22 | /** 23 | * Client callback handler for LLM operations 24 | * Set when client provides their own LLM implementation 25 | */ 26 | export type ClientLLMCallback = ( 27 | operation: string, 28 | payload: Record 29 | ) => Promise; 30 | -------------------------------------------------------------------------------- /packages/runtime/src/approval/handler.ts: -------------------------------------------------------------------------------- 1 | /** 2 | */ 3 | import type { ApprovalRequest, ApprovalResponse } from './types'; 4 | 5 | /** 6 | * Global approval handler that must be set by the execution context 7 | */ 8 | let approvalHandler: ((request: ApprovalRequest) => Promise) | null = null; 9 | 10 | /** 11 | * Initialize the approval system with a custom handler 12 | */ 13 | export function initializeApproval( 14 | handler: (request: ApprovalRequest) => Promise 15 | ): void { 16 | approvalHandler = handler; 17 | } 18 | 19 | /** 20 | * Get the current approval handler 21 | */ 22 | export function getApprovalHandler(): 23 | | ((request: ApprovalRequest) => Promise) 24 | | null { 25 | return approvalHandler; 26 | } 27 | -------------------------------------------------------------------------------- /packages/atp-compiler/src/runtime/batch-parallel.ts: -------------------------------------------------------------------------------- 1 | import { BatchPauseExecutionError } from './errors.js'; 2 | import type { BatchCallInfo } from '../types.js'; 3 | import { 4 | nextSequenceNumber, 5 | getCachedResult, 6 | getCallSequenceNumber, 7 | } from '@mondaydotcomorg/atp-runtime'; 8 | 9 | export async function batchParallel( 10 | batchCalls: BatchCallInfo[], 11 | parallelId: string 12 | ): Promise { 13 | const currentSequence = getCallSequenceNumber(); 14 | const cachedResult = getCachedResult(currentSequence); 15 | if (cachedResult !== undefined) { 16 | nextSequenceNumber(); 17 | return cachedResult as T[]; 18 | } 19 | 20 | const sequenceForPause = nextSequenceNumber(); 21 | throw new BatchPauseExecutionError(batchCalls, parallelId, sequenceForPause); 22 | } 23 | -------------------------------------------------------------------------------- /packages/atp-compiler/jest.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | roots: ['/__tests__'], 5 | testMatch: ['**/*.test.ts'], 6 | moduleNameMapper: { 7 | '^(\\.{1,2}/.*)\\.js$': '$1', 8 | '^@mondaydotcomorg/atp-runtime$': '/../runtime/src/index.ts', 9 | '^@mondaydotcomorg/atp-protocol$': '/../protocol/src/index.ts', 10 | }, 11 | extensionsToTreatAsEsm: ['.ts'], 12 | transform: { 13 | '^.+\\.tsx?$': [ 14 | 'ts-jest', 15 | { 16 | useESM: true, 17 | }, 18 | ], 19 | }, 20 | collectCoverageFrom: ['src/**/*.ts', '!src/**/*.d.ts', '!src/index.ts'], 21 | coverageThreshold: { 22 | global: { 23 | branches: 95, 24 | functions: 95, 25 | lines: 95, 26 | statements: 95, 27 | }, 28 | }, 29 | }; 30 | -------------------------------------------------------------------------------- /packages/server/src/utils/info.ts: -------------------------------------------------------------------------------- 1 | export interface ServerLimits { 2 | maxTimeout: number; 3 | maxMemory: number; 4 | maxLLMCalls: number; 5 | } 6 | 7 | export interface ServerInfo { 8 | version: string; 9 | capabilities: { 10 | execution: boolean; 11 | search: boolean; 12 | streaming: boolean; 13 | llmCalls: boolean; 14 | }; 15 | limits: ServerLimits; 16 | } 17 | 18 | /** 19 | * Generates server information object 20 | */ 21 | export function getServerInfo(limits: ServerLimits): ServerInfo { 22 | return { 23 | version: '1.0.0', 24 | capabilities: { execution: true, search: true, streaming: false, llmCalls: true }, 25 | limits: { 26 | maxTimeout: limits.maxTimeout, 27 | maxMemory: limits.maxMemory, 28 | maxLLMCalls: limits.maxLLMCalls, 29 | }, 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /packages/client/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './client.js'; 2 | export * from './generator.js'; 3 | export * from './tools.js'; 4 | export * from './core/types.js'; 5 | export * from './errors.js'; 6 | 7 | export { ExecutionStatus } from '@mondaydotcomorg/atp-protocol'; 8 | export type { RuntimeAPIName } from '@mondaydotcomorg/atp-runtime'; 9 | export type { Tool, ToolName } from './tools/types.js'; 10 | export { ToolNames } from './tools/types.js'; 11 | export { 12 | searchApiInputSchema, 13 | executeCodeInputSchema, 14 | exploreApiInputSchema, 15 | fetchAllApisInputSchema, 16 | } from './tools/index.js'; 17 | export type { AgentToolProtocolClientOptions } from './client.js'; 18 | export { InProcessSession } from './core/in-process-session.js'; 19 | export type { ISession } from './core/session.js'; 20 | -------------------------------------------------------------------------------- /packages/providers/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-providers", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "packages/providers/src", 5 | "projectType": "library", 6 | "targets": { 7 | "build": { 8 | "executor": "nx:run-commands", 9 | "outputs": ["{workspaceRoot}/packages/providers/dist"], 10 | "options": { 11 | "command": "cd packages/providers && npm run build" 12 | } 13 | }, 14 | "clean": { 15 | "executor": "nx:run-commands", 16 | "options": { 17 | "command": "rm -rf packages/providers/dist" 18 | } 19 | }, 20 | "lint": { 21 | "executor": "nx:run-commands", 22 | "options": { 23 | "command": "cd packages/providers && npm run lint" 24 | } 25 | } 26 | }, 27 | "tags": ["atp-core"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/provenance/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-provenance", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "packages/provenance/src", 5 | "projectType": "library", 6 | "targets": { 7 | "build": { 8 | "executor": "nx:run-commands", 9 | "outputs": ["{workspaceRoot}/packages/provenance/dist"], 10 | "options": { 11 | "command": "cd packages/provenance && npm run build" 12 | } 13 | }, 14 | "clean": { 15 | "executor": "nx:run-commands", 16 | "options": { 17 | "command": "rm -rf packages/provenance/dist" 18 | } 19 | }, 20 | "lint": { 21 | "executor": "nx:run-commands", 22 | "options": { 23 | "command": "cd packages/provenance && npm run lint" 24 | } 25 | } 26 | }, 27 | "tags": ["atp-core"] 28 | } 29 | -------------------------------------------------------------------------------- /packages/atp-compiler/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-compiler", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "packages/atp-compiler/src", 5 | "projectType": "library", 6 | "targets": { 7 | "build": { 8 | "executor": "nx:run-commands", 9 | "outputs": ["{workspaceRoot}/packages/atp-compiler/dist"], 10 | "options": { 11 | "command": "cd packages/atp-compiler && npm run build" 12 | } 13 | }, 14 | "clean": { 15 | "executor": "nx:run-commands", 16 | "options": { 17 | "command": "rm -rf packages/atp-compiler/dist" 18 | } 19 | }, 20 | "lint": { 21 | "executor": "nx:run-commands", 22 | "options": { 23 | "command": "cd packages/atp-compiler && npm run lint" 24 | } 25 | } 26 | }, 27 | "tags": ["atp-core"] 28 | } 29 | -------------------------------------------------------------------------------- /examples/langchain-react-agent/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "langchain-react-agent-example", 3 | "version": "1.0.0", 4 | "private": true, 5 | "description": "Production-ready LangChain React Agent with ATP integration", 6 | "type": "module", 7 | "scripts": { 8 | "start": "NODE_OPTIONS='--no-node-snapshot' tsx agent.ts", 9 | "start:simple": "NODE_OPTIONS='--no-node-snapshot' tsx simple-agent.ts", 10 | "discover": "NODE_OPTIONS='--no-node-snapshot' tsx runtime-discovery.ts" 11 | }, 12 | "dependencies": { 13 | "@langchain/core": "^0.3.78", 14 | "@langchain/langgraph": "^0.2.0", 15 | "@langchain/openai": "^0.3.0", 16 | "@mondaydotcomorg/atp-langchain": "workspace:*", 17 | "langchain": "^0.3.35", 18 | "zod": "^4.1.11" 19 | }, 20 | "devDependencies": { 21 | "tsx": "^4.7.0", 22 | "typescript": "^5.3.3" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/client/src/errors.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Base error class for exceptions thrown by client callbacks that should 3 | * be propagated through the execution flow rather than being caught and 4 | * converted to error results. 5 | * 6 | * Use this when client-side service providers need to interrupt normal 7 | * execution flow (e.g., for human-in-the-loop workflows, custom control flow). 8 | * 9 | * @example 10 | * ```typescript 11 | * class CustomInterruptException extends ClientCallbackError { 12 | * constructor(message: string, public data: any) { 13 | * super(message); 14 | * this.name = 'CustomInterruptException'; 15 | * } 16 | * } 17 | * ``` 18 | */ 19 | export class ClientCallbackError extends Error { 20 | constructor(message: string) { 21 | super(message); 22 | this.name = 'ClientCallbackError'; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/quickstart/README.md: -------------------------------------------------------------------------------- 1 | # Quickstart Example 2 | 3 | A complete end-to-end example demonstrating OpenAPI and MCP integration with the Agent Tool Protocol. 4 | 5 | ## Features 6 | 7 | - ✅ OpenAPI/Swagger 2.0 support (Petstore API) 8 | - ✅ MCP integration (Playwright) 9 | - ✅ Data filtering, mapping, and transformation 10 | - ✅ Self-contained (no external server required) 11 | 12 | ## Usage 13 | 14 | ```bash 15 | npm start 16 | ``` 17 | 18 | ## What it does 19 | 20 | 1. Starts an ATP server 21 | 2. Loads the Petstore API from OpenAPI spec 22 | 3. Connects to Playwright MCP server 23 | 4. Executes code that: 24 | - Fetches pets from the Petstore API 25 | - Filters and maps pet categories 26 | - Returns aggregated results 27 | 28 | ## Environment Variables 29 | 30 | None required. The example uses a default JWT secret for development. 31 | -------------------------------------------------------------------------------- /packages/providers/src/index.ts: -------------------------------------------------------------------------------- 1 | export { MemoryCache } from './cache/memory.js'; 2 | export { RedisCache } from './cache/redis.js'; 3 | export { FileCache } from './cache/file.js'; 4 | 5 | export { EnvAuthProvider } from './auth/env.js'; 6 | 7 | export * from './oauth/index.js'; 8 | 9 | export { JSONLAuditSink } from './audit/jsonl.js'; 10 | export { OpenTelemetryAuditSink } from './audit/opentelemetry.js'; 11 | 12 | export { 13 | OTelCounter, 14 | OTelHistogram, 15 | OTelSpan, 16 | OTelAttribute, 17 | METRIC_CONFIGS, 18 | OTEL_SERVICE_NAME, 19 | OTEL_TRACER_NAME, 20 | OTEL_METER_NAME, 21 | ATTRIBUTE_PREFIX_TOOL, 22 | ATTRIBUTE_PREFIX_METADATA, 23 | } from './audit/otel-metrics.js'; 24 | 25 | export type { 26 | CacheProvider, 27 | AuthProvider, 28 | AuditSink, 29 | AuditEvent, 30 | AuditFilter, 31 | UserCredentialData, 32 | } from '@mondaydotcomorg/atp-protocol'; 33 | -------------------------------------------------------------------------------- /packages/server/src/utils/error.ts: -------------------------------------------------------------------------------- 1 | import { ServerResponse } from 'node:http'; 2 | import { log } from '@mondaydotcomorg/atp-runtime'; 3 | 4 | /** 5 | * Handles HTTP request errors and sends appropriate responses 6 | */ 7 | export function handleError( 8 | res: ServerResponse, 9 | error: Error & { status?: number }, 10 | requestId: string, 11 | additionalHeaders?: Map 12 | ): void { 13 | const status = error.status || 500; 14 | log.error('Request failed', { requestId, error: error.message, stack: error.stack }); 15 | 16 | const headers: Record = { 'Content-Type': 'application/json' }; 17 | if (additionalHeaders) { 18 | for (const [key, value] of additionalHeaders.entries()) { 19 | headers[key] = value; 20 | } 21 | } 22 | 23 | res.writeHead(status, headers); 24 | res.end(JSON.stringify({ error: error.message, requestId })); 25 | } 26 | -------------------------------------------------------------------------------- /__tests__/setup.ts: -------------------------------------------------------------------------------- 1 | import { resetAllExecutionState, cleanupOldExecutionStates } from '@mondaydotcomorg/atp-runtime'; 2 | 3 | /** 4 | * Global test setup - runs before each test file 5 | * 6 | * This ensures that execution state is properly cleaned up between tests 7 | * to prevent test pollution and state leakage. 8 | */ 9 | 10 | beforeEach(() => { 11 | resetAllExecutionState(); 12 | if (global.gc) { 13 | global.gc(); 14 | } 15 | }); 16 | 17 | afterEach(() => { 18 | resetAllExecutionState(); 19 | cleanupOldExecutionStates(0); 20 | if (global.gc) { 21 | global.gc(); 22 | } 23 | }); 24 | 25 | if (typeof afterAll !== 'undefined') { 26 | afterAll(() => { 27 | resetAllExecutionState(); 28 | cleanupOldExecutionStates(0); 29 | if (global.gc) { 30 | try { 31 | global.gc(); 32 | global.gc(); 33 | } catch (e) { 34 | // Ignore if GC not available 35 | } 36 | } 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /packages/vercel-ai-sdk/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-vercel-sdk", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "packages/vercel-ai-sdk/src", 5 | "projectType": "library", 6 | "targets": { 7 | "build": { 8 | "executor": "nx:run-commands", 9 | "outputs": ["{projectRoot}/dist"], 10 | "options": { 11 | "command": "cd packages/vercel-ai-sdk && npm run build" 12 | } 13 | }, 14 | "lint": { 15 | "executor": "nx:run-commands", 16 | "options": { 17 | "command": "tsc --noEmit -p packages/vercel-ai-sdk/tsconfig.json" 18 | } 19 | }, 20 | "test": { 21 | "executor": "nx:run-commands", 22 | "options": { 23 | "command": "cd packages/vercel-ai-sdk && NODE_OPTIONS='--no-node-snapshot' jest --runInBand --forceExit --testTimeout=30000" 24 | } 25 | } 26 | }, 27 | "tags": ["type:library", "scope:integration"] 28 | } 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules 3 | .yarn/* 4 | !.yarn/patches 5 | !.yarn/plugins 6 | !.yarn/releases 7 | !.yarn/sdks 8 | !.yarn/versions 9 | .pnp.* 10 | 11 | # Build outputs 12 | dist 13 | build 14 | *.tsbuildinfo 15 | 16 | # Environment 17 | .env 18 | .env.local 19 | .env.*.local 20 | 21 | # Logs 22 | logs 23 | *.log 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | pnpm-debug.log* 28 | 29 | # Inspector config and chat history (contains encrypted API keys and user data) 30 | inspector/config/ 31 | inspector/chat-history/ 32 | 33 | # OS 34 | .DS_Store 35 | Thumbs.db 36 | 37 | # IDE 38 | .vscode 39 | .idea 40 | *.swp 41 | *.swo 42 | *~ 43 | 44 | # Testing 45 | coverage 46 | .nyc_output 47 | 48 | # Nx 49 | .nx 50 | 51 | # Misc 52 | .cache 53 | temp 54 | tmp 55 | inspector/resources.json 56 | .cursor/rules/nx-rules.mdc 57 | .github/instructions/nx.instructions.md 58 | 59 | examples/policy-ui-demo 60 | -------------------------------------------------------------------------------- /packages/mcp-adapter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist", 6 | "composite": true, 7 | "baseUrl": "../..", 8 | "paths": { 9 | "@mondaydotcomorg/atp-protocol": ["packages/protocol/src/index.ts"], 10 | "@mondaydotcomorg/atp-server": ["packages/server/src/index.ts"], 11 | "@mondaydotcomorg/atp-client": ["packages/client/src/index.ts"], 12 | "@mondaydotcomorg/atp-runtime": ["packages/runtime/src/index.ts"], 13 | "@mondaydotcomorg/atp-mcp-adapter": ["packages/mcp-adapter/src/index.ts"], 14 | "@mondaydotcomorg/atp-langchain": ["packages/langchain/src/index.ts"], 15 | "@agent-tool-protocol/cli": ["packages/cli/src/index.ts"] 16 | } 17 | }, 18 | "include": ["src/**/*"], 19 | "exclude": ["node_modules", "dist", "**/*.test.ts"], 20 | "references": [{ "path": "../protocol" }, { "path": "../server" }, { "path": "../client" }] 21 | } 22 | -------------------------------------------------------------------------------- /examples/framework-integration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "atp-framework-integration-examples", 3 | "version": "1.0.0", 4 | "private": true, 5 | "type": "module", 6 | "description": "Examples of integrating ATP with Express, Fastify, and raw Node.js", 7 | "scripts": { 8 | "express": "NODE_OPTIONS='--no-node-snapshot' tsx express-example.ts", 9 | "fastify": "NODE_OPTIONS='--no-node-snapshot' tsx fastify-example.ts", 10 | "raw": "NODE_OPTIONS='--no-node-snapshot' tsx raw-handler-example.ts" 11 | }, 12 | "dependencies": { 13 | "@fastify/cors": "^9.0.1", 14 | "@fastify/rate-limit": "^9.1.0", 15 | "@mondaydotcomorg/atp-server": "workspace:*", 16 | "cors": "^2.8.5", 17 | "express": "^4.18.2", 18 | "express-rate-limit": "^7.1.5", 19 | "fastify": "^4.26.0" 20 | }, 21 | "devDependencies": { 22 | "@types/cors": "^2.8.17", 23 | "@types/express": "^4.17.21", 24 | "tsx": "^4.7.0", 25 | "typescript": "^5.3.3" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/google-calendar-agent/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "google-calendar-agent-example", 3 | "version": "1.0.0", 4 | "description": "Real-world LangChain agent for smart Google Calendar scheduling using ATP + MCP", 5 | "type": "module", 6 | "scripts": { 7 | "auth": "./auth/generate-token.sh", 8 | "chat:mcp": "NODE_OPTIONS='--no-node-snapshot' npx tsx mcp/interactive-agent.ts", 9 | "chat:atp": "./atp/start-code-agent.sh" 10 | }, 11 | "dependencies": { 12 | "@langchain/langgraph": "^0.2.20", 13 | "@langchain/openai": "^0.3.14", 14 | "@mondaydotcomorg/atp-client": "workspace:*", 15 | "@mondaydotcomorg/atp-langchain": "workspace:*", 16 | "@mondaydotcomorg/atp-mcp-adapter": "workspace:*", 17 | "@mondaydotcomorg/atp-server": "workspace:*", 18 | "dotenv": "^16.4.5", 19 | "tsx": "^4.19.2" 20 | }, 21 | "keywords": [ 22 | "langchain", 23 | "atp", 24 | "mcp", 25 | "google-calendar", 26 | "agent", 27 | "oauth" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /packages/atp-compiler/src/runtime/context.ts: -------------------------------------------------------------------------------- 1 | import type { RuntimeContext } from '../types.js'; 2 | 3 | const contextStack: RuntimeContext[] = []; 4 | 5 | export function setRuntimeContext(context: RuntimeContext): void { 6 | contextStack.push(context); 7 | } 8 | 9 | export function getRuntimeContext(): RuntimeContext { 10 | const context = contextStack[contextStack.length - 1]; 11 | if (!context) { 12 | throw new Error('No runtime context available. Compiler runtime not properly initialized.'); 13 | } 14 | return context; 15 | } 16 | 17 | export function clearRuntimeContext(): void { 18 | contextStack.pop(); 19 | } 20 | 21 | export function hasRuntimeContext(): boolean { 22 | return contextStack.length > 0; 23 | } 24 | 25 | let idCounter = 0; 26 | 27 | export function generateUniqueId(prefix: string): string { 28 | return `${prefix}_${Date.now()}_${idCounter++}`; 29 | } 30 | 31 | export function resetIdCounter(): void { 32 | idCounter = 0; 33 | } 34 | -------------------------------------------------------------------------------- /packages/runtime/src/embedding/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | /** 4 | * Calculate cosine similarity between two vectors 5 | */ 6 | export function cosineSimilarity(vec1: number[], vec2: number[]): number { 7 | if (vec1.length !== vec2.length) { 8 | throw new Error(`Vectors must have the same length (${vec1.length} vs ${vec2.length})`); 9 | } 10 | 11 | let dotProduct = 0; 12 | let norm1 = 0; 13 | let norm2 = 0; 14 | 15 | for (let i = 0; i < vec1.length; i++) { 16 | dotProduct += vec1[i]! * vec2[i]!; 17 | norm1 += vec1[i]! * vec1[i]!; 18 | norm2 += vec2[i]! * vec2[i]!; 19 | } 20 | 21 | const denominator = Math.sqrt(norm1) * Math.sqrt(norm2); 22 | if (denominator === 0) { 23 | return 0; 24 | } 25 | 26 | return dotProduct / denominator; 27 | } 28 | 29 | /** 30 | * Generate a unique ID for an embedding 31 | */ 32 | export function generateEmbeddingId(index: number = 0): string { 33 | return `emb_${Date.now()}_${index}_${Math.random().toString(36).slice(2)}`; 34 | } 35 | -------------------------------------------------------------------------------- /packages/server/src/handlers/search.handler.ts: -------------------------------------------------------------------------------- 1 | import type { RequestContext, ResolvedServerConfig } from '../core/config.js'; 2 | import type { SearchEngine } from '../search/index.js'; 3 | 4 | export async function handleSearch( 5 | ctx: RequestContext, 6 | searchEngine: SearchEngine, 7 | config: ResolvedServerConfig 8 | ): Promise { 9 | const searchOptions = ctx.body as any; 10 | const results = await searchEngine.search( 11 | searchOptions, 12 | ctx.userId, 13 | ctx.auth, 14 | config.discovery.scopeFiltering 15 | ); 16 | return { results }; 17 | } 18 | 19 | export async function handleSearchQuery( 20 | ctx: RequestContext, 21 | searchEngine: SearchEngine, 22 | config: ResolvedServerConfig 23 | ): Promise { 24 | const query = ctx.query.query || ctx.query.keyword || ''; 25 | const results = await searchEngine.search( 26 | { query }, 27 | ctx.userId, 28 | ctx.auth, 29 | config.discovery.scopeFiltering 30 | ); 31 | return { results }; 32 | } 33 | -------------------------------------------------------------------------------- /packages/client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist", 6 | "composite": true, 7 | "baseUrl": "../..", 8 | "paths": { 9 | "@mondaydotcomorg/atp-protocol": ["packages/protocol/src/index.ts"], 10 | "@mondaydotcomorg/atp-provenance": ["packages/provenance/src/index.ts"], 11 | "@mondaydotcomorg/atp-server": ["packages/server/src/index.ts"], 12 | "@mondaydotcomorg/atp-client": ["packages/client/src/index.ts"], 13 | "@mondaydotcomorg/atp-runtime": ["packages/runtime/src/index.ts"], 14 | "@mondaydotcomorg/atp-mcp-adapter": ["packages/mcp-adapter/src/index.ts"], 15 | "@mondaydotcomorg/atp-langchain": ["packages/langchain/src/index.ts"], 16 | "@agent-tool-protocol/cli": ["packages/cli/src/index.ts"] 17 | } 18 | }, 19 | "include": ["src/**/*"], 20 | "exclude": ["node_modules", "dist", "**/*.test.ts"], 21 | "references": [{ "path": "../protocol" }, { "path": "../runtime" }] 22 | } 23 | -------------------------------------------------------------------------------- /packages/server/src/utils/banner.ts: -------------------------------------------------------------------------------- 1 | import type { CacheProvider, AuthProvider, AuditSink } from '@mondaydotcomorg/atp-protocol'; 2 | import { log } from '@mondaydotcomorg/atp-runtime'; 3 | 4 | export interface BannerOptions { 5 | port: number; 6 | cacheProvider?: CacheProvider; 7 | authProvider?: AuthProvider; 8 | auditSink?: AuditSink; 9 | } 10 | 11 | /** 12 | * Prints a startup banner with server information 13 | */ 14 | export function printBanner(options: BannerOptions): void { 15 | const { port, cacheProvider, authProvider, auditSink } = options; 16 | 17 | log.info('ATP Server ready!'); 18 | log.info(`Server running at http://localhost:${port}/`); 19 | log.info(`Type definitions: http://localhost:${port}/openapi.json`); 20 | log.info(`API search: http://localhost:${port}/explorer`); 21 | 22 | if (cacheProvider) log.info(`Cache: ${cacheProvider.name}`); 23 | if (authProvider) log.info(`Auth: ${authProvider.name}`); 24 | if (auditSink) log.info(`Audit: ${auditSink.name}`); 25 | } 26 | -------------------------------------------------------------------------------- /examples/vercel-ai-sdk-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vercel-ai-sdk-example", 3 | "version": "1.0.0", 4 | "type": "module", 5 | "private": true, 6 | "description": "Example demonstrating Vercel AI SDK integration with ATP", 7 | "scripts": { 8 | "server": "NODE_OPTIONS='--no-node-snapshot' ATP_JWT_SECRET=test-secret-key tsx server.ts", 9 | "agent": "NODE_OPTIONS='--no-node-snapshot' tsx agent.ts", 10 | "streaming": "NODE_OPTIONS='--no-node-snapshot' tsx streaming.ts", 11 | "webhook": "NODE_OPTIONS='--no-node-snapshot' tsx webhook-approval.ts" 12 | }, 13 | "dependencies": { 14 | "@ai-sdk/openai": "^1.0.0", 15 | "@mondaydotcomorg/atp-server": "workspace:*", 16 | "@mondaydotcomorg/atp-vercel-sdk": "workspace:*", 17 | "ai": "^4.0.0", 18 | "dotenv": "^16.4.5", 19 | "express": "^4.21.2", 20 | "zod": "^3.25.0" 21 | }, 22 | "devDependencies": { 23 | "@types/express": "^5.0.0", 24 | "@types/node": "^22.10.2", 25 | "tsx": "^4.19.2", 26 | "typescript": "^5.3.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/monday-graphql/show-queries.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Script to show GraphQL queries in real-time from server logs 3 | 4 | LOG_FILE="${1:-/tmp/monday-debug-mode.log}" 5 | 6 | if [ ! -f "$LOG_FILE" ]; then 7 | echo "Log file not found: $LOG_FILE" 8 | echo "Usage: $0 [log-file-path]" 9 | echo "Default: $0 /tmp/monday-debug-mode.log" 10 | exit 1 11 | fi 12 | 13 | echo "📊 Watching GraphQL queries from: $LOG_FILE" 14 | echo "Press Ctrl+C to stop" 15 | echo "" 16 | 17 | # Follow the log file and highlight GraphQL queries 18 | tail -f "$LOG_FILE" | grep --line-buffered -A 15 "GraphQL.*Query:" | while read line; do 19 | if [[ "$line" =~ "GraphQL" ]]; then 20 | echo -e "\n\033[1;34m$line\033[0m" # Blue bold 21 | elif [[ "$line" =~ "Variables:" ]]; then 22 | echo -e "\033[1;33m$line\033[0m" # Yellow bold 23 | elif [[ "$line" =~ "=====" ]]; then 24 | echo -e "\033[0;36m$line\033[0m" # Cyan 25 | else 26 | echo "$line" 27 | fi 28 | done 29 | 30 | 31 | -------------------------------------------------------------------------------- /jest.e2e.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from 'jest'; 2 | import baseConfig from './jest.config.js'; 3 | 4 | /** 5 | * E2E test configuration - runs in band to avoid isolated-vm + Jest worker issues 6 | */ 7 | const config: Config = { 8 | ...baseConfig, 9 | testMatch: ['**/__tests__/e2e/**/*.test.ts'], 10 | // Run tests serially to avoid isolated-vm crashes in Jest workers 11 | maxWorkers: 1, 12 | // Increase timeout for E2E tests 13 | testTimeout: 120000, 14 | // Disable worker threads 15 | workerThreads: false, 16 | // Disable code coverage for E2E tests 17 | collectCoverage: false, 18 | // Better error handling 19 | errorOnDeprecated: false, 20 | // Force exit for E2E tests - HTTP connection pools are hard to clean up 21 | // This is standard practice for integration tests 22 | forceExit: true, 23 | // Set NODE_OPTIONS for isolated-vm and Babel traverse compatibility 24 | testEnvironmentOptions: { 25 | NODE_OPTIONS: '--no-node-snapshot', 26 | }, 27 | }; 28 | 29 | export default config; 30 | -------------------------------------------------------------------------------- /packages/langchain/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "composite": true, 7 | "experimentalDecorators": true, 8 | "emitDecoratorMetadata": true, 9 | "baseUrl": "../..", 10 | "paths": { 11 | "@mondaydotcomorg/atp-protocol": ["packages/protocol/src/index.ts"], 12 | "@mondaydotcomorg/atp-server": ["packages/server/src/index.ts"], 13 | "@mondaydotcomorg/atp-client": ["packages/client/src/index.ts"], 14 | "@mondaydotcomorg/atp-runtime": ["packages/runtime/src/index.ts"], 15 | "@mondaydotcomorg/atp-mcp-adapter": ["packages/mcp-adapter/src/index.ts"], 16 | "@mondaydotcomorg/atp-langchain": ["packages/langchain/src/index.ts"], 17 | "@agent-tool-protocol/cli": ["packages/cli/src/index.ts"] 18 | } 19 | }, 20 | "include": ["src/**/*"], 21 | "exclude": ["node_modules", "dist", "**/*.test.ts"], 22 | "references": [{ "path": "../protocol" }, { "path": "../client" }, { "path": "../runtime" }] 23 | } 24 | -------------------------------------------------------------------------------- /examples/opentelemetry/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@agent-tool-protocol/example-opentelemetry", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "tsx server.ts", 7 | "jaeger": "docker run -d --name jaeger -e COLLECTOR_OTLP_ENABLED=true -p 16686:16686 -p 4318:4318 jaegertracing/all-in-one:latest" 8 | }, 9 | "dependencies": { 10 | "@mondaydotcomorg/atp-protocol": "workspace:*", 11 | "@mondaydotcomorg/atp-providers": "workspace:*", 12 | "@mondaydotcomorg/atp-server": "workspace:*", 13 | "@opentelemetry/api": "^1.9.0", 14 | "@opentelemetry/auto-instrumentations-node": "^0.53.0", 15 | "@opentelemetry/core": "^1.29.0", 16 | "@opentelemetry/exporter-metrics-otlp-http": "^0.56.0", 17 | "@opentelemetry/exporter-trace-otlp-http": "^0.56.0", 18 | "@opentelemetry/resources": "^1.29.0", 19 | "@opentelemetry/sdk-metrics": "^1.29.0", 20 | "@opentelemetry/sdk-node": "^0.56.0", 21 | "@opentelemetry/semantic-conventions": "^1.29.0" 22 | }, 23 | "devDependencies": { 24 | "tsx": "^4.7.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/openapi-example/server.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * OpenAPI Example - Load APIs from OpenAPI specs 3 | * Shows how to load and filter OpenAPI specifications 4 | */ 5 | 6 | import { createServer, loadOpenAPI } from '@mondaydotcomorg/atp-server'; 7 | import { join, dirname } from 'node:path'; 8 | import { fileURLToPath } from 'node:url'; 9 | 10 | const __dirname = dirname(fileURLToPath(import.meta.url)); 11 | 12 | const server = createServer(); 13 | 14 | // Load local OpenAPI spec 15 | const petstore = await loadOpenAPI(join(__dirname, 'petstore-api.json'), { 16 | name: 'petstore', 17 | filter: { 18 | // Only include these HTTP methods 19 | methods: ['GET', 'POST'], 20 | }, 21 | }); 22 | 23 | server.use(petstore); 24 | 25 | await server.listen(3000); 26 | console.log('\n✨ Try these:'); 27 | console.log(' GET http://localhost:3000/api/definitions'); 28 | console.log(' POST http://localhost:3000/api/execute'); 29 | console.log('\nExample code:'); 30 | console.log(' const pets = await api.listPets({ limit: 10 });'); 31 | console.log(' return pets;\n'); 32 | -------------------------------------------------------------------------------- /packages/runtime/src/utils.ts: -------------------------------------------------------------------------------- 1 | export interface RetryOptions { 2 | maxAttempts: number; 3 | delayMs: number; 4 | } 5 | 6 | export const utils = { 7 | async sleep(ms: number): Promise { 8 | return new Promise((resolve) => setTimeout(resolve, ms)); 9 | }, 10 | 11 | async retry(fn: () => Promise, options: RetryOptions): Promise { 12 | let lastError: Error | undefined; 13 | for (let attempt = 1; attempt <= options.maxAttempts; attempt++) { 14 | try { 15 | return await fn(); 16 | } catch (error) { 17 | lastError = error as Error; 18 | if (attempt < options.maxAttempts) { 19 | await this.sleep(options.delayMs); 20 | } 21 | } 22 | } 23 | throw lastError; 24 | }, 25 | 26 | async parallel(tasks: Array<() => Promise>): Promise { 27 | return Promise.all(tasks.map((task) => task())); 28 | }, 29 | 30 | async sequence(tasks: Array<() => Promise>): Promise { 31 | const results: T[] = []; 32 | for (const task of tasks) { 33 | results.push(await task()); 34 | } 35 | return results; 36 | }, 37 | }; 38 | -------------------------------------------------------------------------------- /examples/monday-graphql/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "monday-graphql-example", 3 | "version": "1.0.0", 4 | "type": "module", 5 | "scripts": { 6 | "start": "sh -c 'export $(grep -v \"^#\" ../../.env | xargs) && NODE_OPTIONS=\"--no-node-snapshot\" tsx server.ts'", 7 | "start:debug": "sh -c 'export $(grep -v \"^#\" ../../.env | xargs) && DEBUG_GRAPHQL=true NODE_OPTIONS=\"--no-node-snapshot\" tsx server.ts'", 8 | "agent": "tsx agent.ts", 9 | "chat": "sh -c 'export $(grep -v \"^#\" ../../.env | xargs) && NODE_OPTIONS=\"--no-node-snapshot\" tsx interactive-agent.ts'", 10 | "chat:debug": "sh -c 'export $(grep -v \"^#\" ../../.env | xargs) && DEBUG_GRAPHQL=true NODE_OPTIONS=\"--no-node-snapshot\" tsx interactive-agent.ts'" 11 | }, 12 | "dependencies": { 13 | "@langchain/core": "^0.2.0", 14 | "@langchain/langgraph": "^0.0.19", 15 | "@langchain/openai": "^0.1.0", 16 | "@mondaydotcomorg/atp-client": "workspace:*", 17 | "@mondaydotcomorg/atp-langchain": "workspace:*", 18 | "@mondaydotcomorg/atp-server": "workspace:*", 19 | "dotenv": "^16.4.1", 20 | "tsx": "^4.7.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/langchain-quickstart/README.md: -------------------------------------------------------------------------------- 1 | # LangChain Agent Example 2 | 3 | Demonstrates how to use ATP with LangChain/LangGraph to create autonomous agents that can interact with APIs. 4 | 5 | ## Features 6 | 7 | - ✅ LangChain/LangGraph integration 8 | - ✅ Autonomous agent decision-making 9 | - ✅ OpenAPI/Swagger 2.0 support (Petstore API) 10 | - ✅ Self-contained (no external server required) 11 | 12 | ## Usage 13 | 14 | ```bash 15 | export OPENAI_API_KEY=sk-... 16 | npm start 17 | ``` 18 | 19 | ## What it does 20 | 21 | 1. Starts an ATP server with the Petstore API 22 | 2. Creates a LangChain agent with ATP tools 23 | 3. Gives the agent a task to fetch and analyze pets 24 | 4. The agent autonomously: 25 | - Decides which ATP tools to use 26 | - Generates and executes ATP code 27 | - Processes API responses 28 | - Returns a natural language summary 29 | 30 | ## Environment Variables 31 | 32 | - `OPENAI_API_KEY` - **Required**: Your OpenAI API key 33 | 34 | ## Output 35 | 36 | The agent will respond with information about available pets, including: 37 | 38 | - Total count of available pets 39 | - Example pet names from the API 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 monday.com Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/atp-compiler/src/index.ts: -------------------------------------------------------------------------------- 1 | // Core exports 2 | export * from './types.js'; 3 | export * from './transformer/index.js'; 4 | export * from './runtime/index.js'; 5 | 6 | // Compiler interface exports 7 | export * from './types/compiler-interface.js'; 8 | 9 | // Plugin system exports 10 | export * from './plugin-system/index.js'; 11 | 12 | // Main exports 13 | export { ATPCompiler } from './transformer/index.js'; 14 | export { initializeRuntime, cleanupRuntime } from './runtime/index.js'; 15 | export { PluggableCompiler } from './plugin-system/pluggable-compiler.js'; 16 | export { PluginRegistry } from './plugin-system/plugin-api.js'; 17 | export { createDefaultCompiler } from './plugin-system/create-default-compiler.js'; 18 | 19 | // Plugin type exports for convenience 20 | export type { 21 | CompilerPlugin, 22 | DetectionPlugin, 23 | TransformationPlugin, 24 | OptimizerPlugin, 25 | ValidatorPlugin, 26 | PluginContext, 27 | BabelVisitor, 28 | } from './plugin-system/plugin-api.js'; 29 | export type { ATPCompilerLike } from './plugin-system/create-default-compiler.js'; 30 | 31 | // Compiler interface type exports 32 | export type { ICompiler, CacheStats } from './types/compiler-interface.js'; 33 | -------------------------------------------------------------------------------- /packages/atp-compiler/src/plugin-system/default-plugins/detection-plugin.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Default Detection Plugin 3 | * Wraps the existing AsyncIterationDetector 4 | */ 5 | 6 | import type * as t from '@babel/types'; 7 | import type { DetectionPlugin } from '../plugin-api.js'; 8 | import type { CompilerConfig, AsyncPattern, DetectionResult } from '../../types.js'; 9 | import { AsyncIterationDetector } from '../../transformer/detector.js'; 10 | 11 | export class DefaultDetectionPlugin implements DetectionPlugin { 12 | name = 'atp-default-detector'; 13 | version = '1.0.0'; 14 | priority = 100; 15 | patterns: AsyncPattern[] = [ 16 | 'for-of-await', 17 | 'while-await', 18 | 'map-async', 19 | 'forEach-async', 20 | 'filter-async', 21 | 'reduce-async', 22 | 'find-async', 23 | 'some-async', 24 | 'every-async', 25 | 'flatMap-async', 26 | 'promise-all', 27 | 'promise-allSettled', 28 | ]; 29 | 30 | private detector: AsyncIterationDetector; 31 | 32 | constructor() { 33 | this.detector = new AsyncIterationDetector(); 34 | } 35 | 36 | async detect(code: string, ast: t.File): Promise { 37 | // Use existing detector 38 | return this.detector.detect(code); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /env.example: -------------------------------------------------------------------------------- 1 | # Agent Tool Protocol - Environment Variables 2 | 3 | # REQUIRED: JWT secret for token signing (generate with: openssl rand -base64 32) 4 | ATP_JWT_SECRET=EUnWEFj8fgMC2wAmN5bKkDEUVdVzF1XExaApukaTJQo= 5 | 6 | # Optional: Node environment 7 | NODE_ENV=development 8 | 9 | # Optional: Logging level 10 | LOG_LEVEL=info 11 | 12 | # Optional: Server port 13 | PORT=3000 14 | 15 | # Optional: Redis URL for caching (recommended for production) 16 | # REDIS_URL=redis://localhost:6379 17 | 18 | # Optional: OpenTelemetry endpoint 19 | # OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 20 | 21 | # Optional: Enable ATP compiler for pause/resume with batching (default: false) 22 | # ATP_COMPILER_ENABLED=true 23 | 24 | # Optional: Batch size threshold for smart batching (default: 10) 25 | # Controls when to batch vs sequential execution for conditional callbacks 26 | # - 0: Never batch conditionals (always sequential, max early-exit) 27 | # - 5: Conservative (prioritize early-exit for cost savings) 28 | # - 10: Balanced (default - good speed/cost trade-off) 29 | # - 20: Aggressive (prioritize speed over early-exit) 30 | # - 99999: Always batch (maximum parallelism, no early-exit) 31 | # ATP_BATCH_SIZE_THRESHOLD=10 32 | 33 | -------------------------------------------------------------------------------- /packages/atp-compiler/src/runtime/index.ts: -------------------------------------------------------------------------------- 1 | export * from './errors.js'; 2 | export * from './context.js'; 3 | export * from './checkpoint-manager.js'; 4 | export * from './resumable-loops.js'; 5 | export * from './resumable-arrays.js'; 6 | export * from './resumable-parallel.js'; 7 | export * from './batch-parallel.js'; 8 | export * from './runtime-functions.js'; 9 | 10 | import type { CacheProvider } from '@mondaydotcomorg/atp-protocol'; 11 | import { CheckpointManager, setCheckpointManager } from './checkpoint-manager.js'; 12 | import { setRuntimeContext } from './context.js'; 13 | 14 | export interface InitializeRuntimeOptions { 15 | executionId: string; 16 | cache: CacheProvider; 17 | checkpointPrefix?: string; 18 | } 19 | 20 | export function initializeRuntime(options: InitializeRuntimeOptions): void { 21 | const checkpointManager = new CheckpointManager( 22 | options.executionId, 23 | options.cache, 24 | options.checkpointPrefix 25 | ); 26 | 27 | setCheckpointManager(checkpointManager); 28 | 29 | setRuntimeContext({ 30 | executionId: options.executionId, 31 | cache: options.cache, 32 | checkpointPrefix: options.checkpointPrefix, 33 | }); 34 | } 35 | 36 | export function cleanupRuntime(): void {} 37 | -------------------------------------------------------------------------------- /packages/atp-compiler/src/transformer/array-transformer-sequential.ts: -------------------------------------------------------------------------------- 1 | import * as t from '@babel/types'; 2 | import { generateUniqueId } from '../runtime/context.js'; 3 | import { getRuntimeMethodName } from './array-transformer-utils.js'; 4 | 5 | /** 6 | * Transform to sequential execution with checkpoints (fallback) 7 | */ 8 | export function transformToSequential( 9 | path: any, 10 | node: t.CallExpression, 11 | methodName: string, 12 | callback: t.Function, 13 | onTransform: () => void 14 | ): boolean { 15 | const runtimeMethod = getRuntimeMethodName(methodName); 16 | if (!runtimeMethod) { 17 | return false; 18 | } 19 | 20 | const methodId = generateUniqueId(methodName); 21 | const array = (node.callee as t.MemberExpression).object; 22 | const args: t.Expression[] = [array, callback as t.Expression, t.stringLiteral(methodId)]; 23 | 24 | if (methodName === 'reduce' && node.arguments[1]) { 25 | args.push(node.arguments[1] as t.Expression); 26 | } 27 | 28 | const runtimeCall = t.awaitExpression( 29 | t.callExpression( 30 | t.memberExpression(t.identifier('__runtime'), t.identifier(runtimeMethod)), 31 | args 32 | ) 33 | ); 34 | 35 | path.replaceWith(runtimeCall); 36 | onTransform(); 37 | return true; 38 | } 39 | -------------------------------------------------------------------------------- /examples/quickstart/server.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Quickstart Example - Get started in 3 lines 3 | * Shows the simplest possible ATP server with custom tools 4 | */ 5 | 6 | import { createServer } from '@mondaydotcomorg/atp-server'; 7 | 8 | const server = createServer(); 9 | 10 | server.tool('greet', { 11 | description: 'Greet someone by name', 12 | input: { name: 'string' }, 13 | handler: async (input: unknown) => { 14 | const { name } = input as { name: string }; 15 | return `Hello, ${name}!`; 16 | }, 17 | }); 18 | 19 | server.tool('calculate', { 20 | description: 'Perform a simple calculation', 21 | input: { 22 | operation: 'string', 23 | a: 'number', 24 | b: 'number', 25 | }, 26 | handler: async (input: unknown) => { 27 | const { operation, a, b } = input as { operation: string; a: number; b: number }; 28 | switch (operation) { 29 | case 'add': 30 | return { result: a + b }; 31 | case 'subtract': 32 | return { result: a - b }; 33 | case 'multiply': 34 | return { result: a * b }; 35 | case 'divide': 36 | return { result: a / b }; 37 | default: 38 | throw new Error('Invalid operation'); 39 | } 40 | }, 41 | }); 42 | 43 | await server.listen(3000); 44 | console.log('Try: http://localhost:3000/api/info'); 45 | -------------------------------------------------------------------------------- /packages/providers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-providers", 3 | "version": "0.19.17", 4 | "description": "Built-in providers for Agent Tool Protocol (cache, auth, audit)", 5 | "type": "module", 6 | "main": "./dist/index.cjs", 7 | "module": "./dist/index.js", 8 | "types": "./dist/index.d.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./dist/index.d.ts", 12 | "import": "./dist/index.js", 13 | "require": "./dist/index.cjs" 14 | } 15 | }, 16 | "scripts": { 17 | "build": "npx tsc --build tsconfig.json && tsup", 18 | "build:tsc": "tsc", 19 | "clean": "rm -rf dist", 20 | "lint": "tsc --noEmit", 21 | "test": "vitest run" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/mondaycom/agent-tool-protocol", 26 | "directory": "packages/providers" 27 | }, 28 | "publishConfig": { 29 | "access": "public" 30 | }, 31 | "keywords": [ 32 | "providers", 33 | "atp", 34 | "api", 35 | "agent" 36 | ], 37 | "dependencies": { 38 | "@mondaydotcomorg/atp-protocol": "0.19.17", 39 | "@mondaydotcomorg/atp-runtime": "0.19.16", 40 | "@opentelemetry/api": "^1.9.0" 41 | }, 42 | "devDependencies": { 43 | "tsup": "^8.5.1", 44 | "typescript": "^5.7.2", 45 | "vitest": "^1.2.1" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /packages/server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist", 6 | "composite": true, 7 | "baseUrl": "../..", 8 | "paths": { 9 | "@mondaydotcomorg/atp-protocol": ["packages/protocol/src/index.ts"], 10 | "@mondaydotcomorg/atp-provenance": ["packages/provenance/src/index.ts"], 11 | "@mondaydotcomorg/atp-providers": ["packages/providers/src/index.ts"], 12 | "@mondaydotcomorg/atp-server": ["packages/server/src/index.ts"], 13 | "@mondaydotcomorg/atp-client": ["packages/client/src/index.ts"], 14 | "@mondaydotcomorg/atp-runtime": ["packages/runtime/src/index.ts"], 15 | "@mondaydotcomorg/atp-mcp-adapter": ["packages/mcp-adapter/src/index.ts"], 16 | "@mondaydotcomorg/atp-langchain": ["packages/langchain/src/index.ts"], 17 | "@mondaydotcomorg/atp-compiler": ["packages/atp-compiler/src/index.ts"], 18 | "@agent-tool-protocol/cli": ["packages/cli/src/index.ts"] 19 | } 20 | }, 21 | "include": ["src/**/*"], 22 | "exclude": ["node_modules", "dist", "**/*.test.ts"], 23 | "references": [ 24 | { "path": "../protocol" }, 25 | { "path": "../provenance" }, 26 | { "path": "../providers" }, 27 | { "path": "../runtime" }, 28 | { "path": "../atp-compiler" } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /packages/vercel-ai-sdk/jest.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node', 5 | roots: [''], 6 | testMatch: ['**/__tests__/**/*.test.ts'], 7 | testPathIgnorePatterns: ['/node_modules/', '/dist/'], 8 | moduleNameMapper: { 9 | '^(\\.{1,2}/.*)\\.js$': '$1', 10 | '^@mondaydotcomorg/atp-protocol$': '/../protocol/src/index.ts', 11 | '^@mondaydotcomorg/atp-runtime$': '/../runtime/src/index.ts', 12 | '^@mondaydotcomorg/atp-provenance$': '/../provenance/src/index.ts', 13 | '^@mondaydotcomorg/atp-compiler$': '/../atp-compiler/src/index.ts', 14 | '^@mondaydotcomorg/atp-server$': '/../server/src/index.ts', 15 | '^@mondaydotcomorg/atp-client$': '/../client/src/index.ts', 16 | '^@mondaydotcomorg/atp-providers$': '/../providers/src/index.ts', 17 | '^zod-to-json-schema$': '/../../__mocks__/zod-to-json-schema/index.js', 18 | }, 19 | transform: { 20 | '^.+\\.tsx?$': [ 21 | 'ts-jest', 22 | { 23 | tsconfig: { 24 | esModuleInterop: true, 25 | allowSyntheticDefaultImports: true, 26 | strict: false, 27 | }, 28 | useESM: false, 29 | }, 30 | ], 31 | }, 32 | transformIgnorePatterns: [], 33 | testTimeout: 30000, 34 | verbose: true, 35 | extensionsToTreatAsEsm: [], 36 | }; 37 | -------------------------------------------------------------------------------- /examples/streaming-events/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "streaming-events-example", 3 | "version": "1.0.0", 4 | "type": "module", 5 | "private": true, 6 | "description": "Real-world example demonstrating ATP streaming events with both LangChain and Vercel AI SDK", 7 | "scripts": { 8 | "server": "NODE_OPTIONS='--no-node-snapshot' tsx server.ts", 9 | "vercel:http": "NODE_OPTIONS='--no-node-snapshot' tsx vercel-http-example.ts", 10 | "vercel:inprocess": "NODE_OPTIONS='--no-node-snapshot' tsx vercel-inprocess-example.ts", 11 | "langchain:http": "NODE_OPTIONS='--no-node-snapshot' tsx langchain-http-example.ts", 12 | "langchain:inprocess": "NODE_OPTIONS='--no-node-snapshot' tsx langchain-inprocess-example.ts" 13 | }, 14 | "dependencies": { 15 | "@ai-sdk/openai": "^1.0.0", 16 | "@langchain/core": "^0.3.78", 17 | "@langchain/langgraph": "^0.2.0", 18 | "@langchain/openai": "^0.3.0", 19 | "@mondaydotcomorg/atp-client": "workspace:*", 20 | "@mondaydotcomorg/atp-langchain": "workspace:*", 21 | "@mondaydotcomorg/atp-protocol": "workspace:*", 22 | "@mondaydotcomorg/atp-server": "workspace:*", 23 | "@mondaydotcomorg/atp-vercel-sdk": "workspace:*", 24 | "ai": "^4.0.0", 25 | "dotenv": "^16.4.5", 26 | "zod": "^3.25.0" 27 | }, 28 | "devDependencies": { 29 | "@types/node": "^22.10.2", 30 | "tsx": "^4.19.2", 31 | "typescript": "^5.3.3" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/runtime/src/pause/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Callback types that can pause execution 3 | */ 4 | export enum CallbackType { 5 | LLM = 'llm', 6 | APPROVAL = 'approval', 7 | EMBEDDING = 'embedding', 8 | TOOL = 'tool', 9 | } 10 | 11 | /** 12 | * LLM callback operations 13 | */ 14 | export enum LLMOperation { 15 | CALL = 'call', 16 | EXTRACT = 'extract', 17 | CLASSIFY = 'classify', 18 | } 19 | 20 | /** 21 | * Embedding callback operations 22 | */ 23 | export enum EmbeddingOperation { 24 | EMBED = 'embed', 25 | SEARCH = 'search', 26 | } 27 | 28 | /** 29 | * Approval callback operations 30 | */ 31 | export enum ApprovalOperation { 32 | REQUEST = 'request', 33 | } 34 | 35 | /** 36 | * Tool callback operations 37 | */ 38 | export enum ToolOperation { 39 | CALL = 'call', 40 | } 41 | 42 | /** 43 | * Thrown when execution needs to pause for client callback 44 | */ 45 | export class PauseExecutionError extends Error { 46 | public readonly type: CallbackType; 47 | public readonly operation: string; 48 | public readonly payload: Record; 49 | 50 | constructor(type: CallbackType, operation: string, payload: Record) { 51 | super(`Execution paused: waiting for ${type}.${operation}`); 52 | this.name = 'PauseExecutionError'; 53 | this.type = type; 54 | this.operation = operation; 55 | this.payload = payload; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /examples/token-refresh/README.md: -------------------------------------------------------------------------------- 1 | # Token Refresh Example 2 | 3 | This example demonstrates how to use the `preRequestHook` to automatically refresh short-lived authentication tokens. 4 | 5 | ## Use Case 6 | 7 | Many authentication systems (OAuth2, OIDC, etc.) issue tokens with short time-to-live (TTL) values, such as: 8 | 9 | - 3 minutes for bearer tokens 10 | - 15 minutes for access tokens 11 | - 1 hour for session tokens 12 | 13 | The `preRequestHook` solves this by automatically refreshing tokens before each request. 14 | 15 | ## Running the Example 16 | 17 | ```bash 18 | # Install dependencies 19 | yarn install 20 | 21 | # Run the example 22 | tsx server.ts 23 | ``` 24 | 25 | ## How It Works 26 | 27 | 1. **Token Manager**: Manages token lifecycle with caching 28 | 2. **Pre-Request Hook**: Intercepts every request to ensure fresh token 29 | 3. **Automatic Refresh**: Only refreshes when token is expired or about to expire 30 | 31 | ## Key Features 32 | 33 | ✅ **Automatic refresh** - No manual token management 34 | ✅ **Efficient caching** - Only refreshes when needed (30-second buffer) 35 | ✅ **Error handling** - Gracefully handles refresh failures 36 | ✅ **Production-ready** - Thread-safe with proper expiry management 37 | 38 | ## See Also 39 | 40 | - [Pre-Request Hook Documentation](../../docs/pre-request-hook.md) 41 | - [Security Best Practices](../../docs/security.md) 42 | -------------------------------------------------------------------------------- /packages/atp-compiler/src/plugin-system/default-plugins/loop-transformer-plugin.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Default Loop Transformer Plugin 3 | * Wraps the existing LoopTransformer 4 | */ 5 | 6 | import type { TransformationPlugin, BabelVisitor } from '../plugin-api.js'; 7 | import type { CompilerConfig, TransformMetadata } from '../../types.js'; 8 | import { LoopTransformer } from '../../transformer/loop-transformer.js'; 9 | 10 | export class DefaultLoopTransformerPlugin implements TransformationPlugin { 11 | name = 'atp-loop-transformer'; 12 | version = '1.0.0'; 13 | priority = 100; 14 | 15 | private transformer: LoopTransformer; 16 | 17 | constructor(batchSizeThreshold?: number) { 18 | this.transformer = new LoopTransformer(batchSizeThreshold); 19 | } 20 | 21 | getVisitor(config: CompilerConfig): BabelVisitor { 22 | return { 23 | ForOfStatement: (path: any) => { 24 | this.transformer.transformForOfLoop(path); 25 | }, 26 | 27 | WhileStatement: (path: any) => { 28 | this.transformer.transformWhileLoop(path); 29 | }, 30 | 31 | ForStatement: (path: any) => { 32 | this.transformer.transformForLoop(path); 33 | }, 34 | }; 35 | } 36 | 37 | getMetadata(): Partial { 38 | return { 39 | loopCount: this.transformer.getTransformCount(), 40 | }; 41 | } 42 | 43 | reset(): void { 44 | this.transformer.resetTransformCount(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/protocol/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-protocol", 3 | "version": "0.19.17", 4 | "description": "Core protocol types and interfaces for Agent Tool Protocol", 5 | "type": "module", 6 | "main": "./dist/index.cjs", 7 | "module": "./dist/index.js", 8 | "types": "./dist/index.d.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./dist/index.d.ts", 12 | "import": "./dist/index.js", 13 | "require": "./dist/index.cjs" 14 | } 15 | }, 16 | "files": [ 17 | "dist", 18 | "src" 19 | ], 20 | "scripts": { 21 | "build": "npx tsc --build tsconfig.json && tsup", 22 | "build:tsc": "tsc -p tsconfig.json", 23 | "dev": "tsc -p tsconfig.json --watch", 24 | "clean": "rm -rf dist *.tsbuildinfo", 25 | "test": "vitest run", 26 | "lint": "tsc --noEmit" 27 | }, 28 | "keywords": [ 29 | "agent", 30 | "protocol", 31 | "atp", 32 | "types", 33 | "ai", 34 | "llm" 35 | ], 36 | "repository": { 37 | "type": "git", 38 | "url": "https://github.com/mondaycom/agent-tool-protocol", 39 | "directory": "packages/protocol" 40 | }, 41 | "license": "MIT", 42 | "dependencies": { 43 | "@mondaydotcomorg/atp-provenance": "0.19.16" 44 | }, 45 | "peerDependencies": { 46 | "zod": "^3.25.0" 47 | }, 48 | "publishConfig": { 49 | "access": "public" 50 | }, 51 | "devDependencies": { 52 | "tsup": "^8.5.1", 53 | "typescript": "^5.3.3", 54 | "vitest": "^1.2.1", 55 | "zod": "^3.25.0" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/client/src/tools/fetch-all-apis.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { zodToJsonSchema } from 'zod-to-json-schema'; 3 | import type { AgentToolProtocolClient } from '../client.js'; 4 | import { ToolNames, type Tool } from './types.js'; 5 | 6 | export const fetchAllApisInputSchema = z.object({ 7 | apiGroups: z.array(z.string()).optional().describe('Optional: Specific API groups to include'), 8 | }); 9 | 10 | type FetchAllApisInput = z.infer; 11 | 12 | export function createFetchAllApisTool(client: AgentToolProtocolClient): Tool { 13 | return { 14 | name: ToolNames.FETCH_ALL_APIS, 15 | description: 16 | 'Get TypeScript definitions of all available APIs. Returns code showing api.add, api.getTodo, etc.', 17 | inputSchema: zodToJsonSchema(fetchAllApisInputSchema) as any, 18 | zodSchema: fetchAllApisInputSchema, 19 | func: async (_input: FetchAllApisInput) => { 20 | try { 21 | const typescript = client.getTypeDefinitions(); 22 | return JSON.stringify( 23 | { 24 | success: true, 25 | typescript, 26 | message: 'Use this TypeScript to understand available api.* functions', 27 | }, 28 | null, 29 | 2 30 | ); 31 | } catch (error: any) { 32 | return JSON.stringify( 33 | { 34 | success: false, 35 | error: error.message, 36 | }, 37 | null, 38 | 2 39 | ); 40 | } 41 | }, 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /packages/runtime/src/metadata/decorators.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Decorator-based metadata system for runtime APIs 3 | * 4 | * These decorators are MARKERS ONLY - they don't extract types at runtime. 5 | * All type extraction happens at BUILD TIME using ts-morph. 6 | * 7 | 8 | /** 9 | * Class decorator to mark a runtime API 10 | * 11 | * This is just a marker - ts-morph extracts all metadata at build time 12 | */ 13 | export function RuntimeAPI(name: string, description: string) { 14 | return function (constructor: T) { 15 | (constructor as any).API_NAME = name; 16 | (constructor as any).API_DESCRIPTION = description; 17 | 18 | return constructor; 19 | }; 20 | } 21 | 22 | /** 23 | * Method decorator to mark a runtime method 24 | * 25 | * This is just a marker - ts-morph extracts types/params at build time 26 | * Only the description and optional param descriptions are stored 27 | */ 28 | export function RuntimeMethod( 29 | description: string, 30 | paramDescriptions?: Record 31 | ) { 32 | return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { 33 | if (!target.constructor.__methods) { 34 | target.constructor.__methods = {}; 35 | } 36 | 37 | target.constructor.__methods[propertyKey] = { 38 | description, 39 | paramDescriptions: paramDescriptions || {}, 40 | }; 41 | 42 | return descriptor; 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /packages/client/src/tools/search-api.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { zodToJsonSchema } from 'zod-to-json-schema'; 3 | import type { AgentToolProtocolClient } from '../client.js'; 4 | import { ToolNames, type Tool } from './types.js'; 5 | 6 | export const searchApiInputSchema = z.object({ 7 | query: z.string().describe('Search query string'), 8 | }); 9 | 10 | type SearchApiInput = z.infer; 11 | 12 | export function createSearchApiTool(client: AgentToolProtocolClient): Tool { 13 | return { 14 | name: ToolNames.SEARCH_API, 15 | description: 16 | 'Search for APIs by keyword. Provide search term as string like "add", "math", "user", etc.', 17 | inputSchema: zodToJsonSchema(searchApiInputSchema) as any, 18 | zodSchema: searchApiInputSchema, 19 | func: async (input: SearchApiInput) => { 20 | try { 21 | const results = await client.searchAPI(input.query); 22 | return JSON.stringify( 23 | { 24 | success: true, 25 | results: results.map((r) => ({ 26 | apiGroup: r.apiGroup, 27 | functionName: r.functionName, 28 | description: r.description, 29 | signature: r.signature, 30 | })), 31 | count: results.length, 32 | }, 33 | null, 34 | 2 35 | ); 36 | } catch (error: any) { 37 | return JSON.stringify( 38 | { 39 | success: false, 40 | error: error.message, 41 | }, 42 | null, 43 | 2 44 | ); 45 | } 46 | }, 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "module": "ESNext", 5 | "lib": ["ES2022"], 6 | "moduleResolution": "bundler", 7 | "resolveJsonModule": true, 8 | "allowJs": true, 9 | "strict": true, 10 | "noUnusedLocals": false, 11 | "noUnusedParameters": false, 12 | "noFallthroughCasesInSwitch": true, 13 | "noUncheckedIndexedAccess": true, 14 | "esModuleInterop": true, 15 | "skipLibCheck": true, 16 | "forceConsistentCasingInFileNames": true, 17 | "declaration": true, 18 | "declarationMap": true, 19 | "sourceMap": true, 20 | "experimentalDecorators": true, 21 | "emitDecoratorMetadata": true, 22 | "baseUrl": ".", 23 | "paths": { 24 | "@mondaydotcomorg/atp-compiler": ["packages/atp-compiler/src/index.ts"], 25 | "@agent-tool-protocol/cli": ["packages/cli/src/index.ts"], 26 | "@mondaydotcomorg/atp-client": ["packages/client/src/index.ts"], 27 | "@mondaydotcomorg/atp-langchain": ["packages/langchain/src/index.ts"], 28 | "@mondaydotcomorg/atp-mcp-adapter": ["packages/mcp-adapter/src/index.ts"], 29 | "@mondaydotcomorg/atp-protocol": ["packages/protocol/src/index.ts"], 30 | "@mondaydotcomorg/atp-provenance": ["packages/provenance/src/index.ts"], 31 | "@mondaydotcomorg/atp-providers": ["packages/providers/src/index.ts"], 32 | "@mondaydotcomorg/atp-runtime": ["packages/runtime/src/index.ts"], 33 | "@mondaydotcomorg/atp-server": ["packages/server/src/index.ts"] 34 | } 35 | }, 36 | "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] 37 | } 38 | -------------------------------------------------------------------------------- /packages/runtime/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './llm/index.js'; 2 | export * from './progress/index.js'; 3 | export * from './cache/index.js'; 4 | export * from './utils.js'; 5 | export * from './approval/index.js'; 6 | export * from './embedding/index.js'; 7 | export * from './registry.js'; 8 | export * from './metadata/index.js'; 9 | 10 | export { log, initializeLogger, shutdownLogger } from './log/index.js'; 11 | export type { LogLevel, LoggerConfig, Logger } from './log/index.js'; 12 | 13 | export { GENERATED_METADATA } from './metadata/generated.js'; 14 | 15 | export { 16 | initializeExecutionState, 17 | setClientLLMCallback, 18 | setPauseForClient, 19 | shouldPauseForClient, 20 | setReplayMode, 21 | getCallSequenceNumber, 22 | isReplayMode, 23 | storeAPICallResult, 24 | getAPICallResults, 25 | clearAPICallResults, 26 | setAPIResultCache, 27 | getAPIResultFromCache, 28 | storeAPIResultInCache, 29 | cleanupExecutionState, 30 | cleanupOldExecutionStates, 31 | resetAllExecutionState, 32 | getExecutionStateStats, 33 | } from './llm/index.js'; 34 | export { initializeCache } from './cache/index.js'; 35 | export { initializeApproval } from './approval/index.js'; 36 | export { setProgressCallback } from './progress/index.js'; 37 | export { initializeVectorStore, clearVectorStore, getVectorStore } from './embedding/index.js'; 38 | 39 | export { 40 | PauseExecutionError, 41 | isPauseError, 42 | pauseForCallback, 43 | CallbackType, 44 | LLMOperation, 45 | EmbeddingOperation, 46 | ApprovalOperation, 47 | ToolOperation, 48 | } from './pause/index.js'; 49 | -------------------------------------------------------------------------------- /examples/google-calendar-agent/auth/README.md: -------------------------------------------------------------------------------- 1 | # Authentication Setup 2 | 3 | This folder contains authentication-related files for Google Calendar OAuth. 4 | 5 | ## Files 6 | 7 | - **`env.example`**: Template for environment variables 8 | - **`generate-token.sh`**: Script to generate OAuth tokens via browser 9 | 10 | ## Setup 11 | 12 | 1. **Copy the environment template to the project root:** 13 | 14 | ```bash 15 | # From the project root (google-calendar-agent/) 16 | cp auth/env.example .env 17 | ``` 18 | 19 | 2. **Edit `.env` in the project root and add your credentials:** 20 | 21 | ```bash 22 | OPENAI_API_KEY=your-openai-api-key 23 | GOOGLE_OAUTH_CREDENTIALS=/path/to/gcp-oauth.keys.json 24 | ``` 25 | 26 | Note: The `.env` file should be in the project root, not in the `auth/` folder. 27 | 28 | 3. **Generate OAuth token:** 29 | 30 | ```bash 31 | npm run auth 32 | ``` 33 | 34 | This will: 35 | - Open your browser for Google OAuth consent 36 | - Save the token to `~/.config/google-calendar-mcp/tokens.json` 37 | 38 | ## Getting OAuth Credentials 39 | 40 | 1. Go to [Google Cloud Console](https://console.cloud.google.com/) 41 | 2. Create or select a project 42 | 3. Enable the Google Calendar API 43 | 4. Create OAuth 2.0 credentials (Desktop app type) 44 | 5. Download the credentials as `gcp-oauth.keys.json` 45 | 6. Set `GOOGLE_OAUTH_CREDENTIALS` to the file path in `.env` 46 | 47 | ## Token Storage 48 | 49 | Tokens are stored in: `~/.config/google-calendar-mcp/tokens.json` 50 | 51 | Both the MCP and ATP agents use the same token location. 52 | -------------------------------------------------------------------------------- /examples/streaming-events/simple-test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple test to verify streaming events work 3 | */ 4 | import { AgentToolProtocolClient } from '@mondaydotcomorg/atp-client'; 5 | import { ATPEventType } from '@mondaydotcomorg/atp-protocol'; 6 | import { server } from './server.js'; 7 | 8 | async function main() { 9 | const client = new AgentToolProtocolClient({ server }); 10 | await client.init({ name: 'test', version: '1.0.0' }); 11 | await client.connect(); 12 | 13 | console.log('🧪 Testing ATP Streaming Events\n'); 14 | console.log('═'.repeat(50)); 15 | 16 | const eventCounts: Record = {}; 17 | 18 | const result = await client.execute(`await api.custom.research({ topic: "AI", depth: 2 })`, { 19 | eventCallback: (event) => { 20 | eventCounts[event.type] = (eventCounts[event.type] || 0) + 1; 21 | 22 | const icons: Record = { 23 | thinking: '💭', 24 | tool_start: '🔧', 25 | tool_end: '✅', 26 | text: '📝', 27 | source: '📚', 28 | progress: '📊', 29 | }; 30 | const icon = icons[event.type] || '📨'; 31 | const dataStr = JSON.stringify(event.data); 32 | console.log(`${icon} [${event.type}] ${dataStr.substring(0, 70)}${dataStr.length > 70 ? '...' : ''}`); 33 | }, 34 | }); 35 | 36 | console.log('\n' + '═'.repeat(50)); 37 | console.log('📊 Event Summary:'); 38 | for (const [type, count] of Object.entries(eventCounts).sort()) { 39 | console.log(` ${type}: ${count}`); 40 | } 41 | console.log('═'.repeat(50)); 42 | console.log('✅ Test completed!'); 43 | } 44 | 45 | main().catch(console.error); 46 | 47 | -------------------------------------------------------------------------------- /packages/server/src/utils/request.ts: -------------------------------------------------------------------------------- 1 | import { IncomingMessage } from 'node:http'; 2 | 3 | /** 4 | * Default maximum request body size (10MB) 5 | */ 6 | export const DEFAULT_MAX_BODY_SIZE = 10 * 1024 * 1024; 7 | 8 | /** 9 | * Reads the full request body as a string 10 | * @param req - The HTTP request 11 | * @param maxSize - Maximum allowed body size in bytes (default: 10MB) 12 | * @returns Promise resolving to the complete body string 13 | * @throws Error if body exceeds maxSize 14 | */ 15 | export function readBody(req: IncomingMessage, maxSize = DEFAULT_MAX_BODY_SIZE): Promise { 16 | return new Promise((resolve, reject) => { 17 | let body = ''; 18 | let size = 0; 19 | 20 | req.on('data', (chunk) => { 21 | size += chunk.length; 22 | 23 | if (size > maxSize) { 24 | req.destroy(); 25 | reject(new Error(`Request body too large (max ${maxSize} bytes)`)); 26 | return; 27 | } 28 | 29 | body += chunk.toString(); 30 | }); 31 | 32 | req.on('end', () => resolve(body)); 33 | req.on('error', reject); 34 | }); 35 | } 36 | 37 | /** 38 | * Reads and parses request body as JSON 39 | * @param req - The HTTP request 40 | * @param maxSize - Maximum allowed body size in bytes 41 | * @returns Promise resolving to the parsed JSON object 42 | */ 43 | export async function readJsonBody( 44 | req: IncomingMessage, 45 | maxSize = DEFAULT_MAX_BODY_SIZE 46 | ): Promise { 47 | const body = await readBody(req, maxSize); 48 | try { 49 | return body ? JSON.parse(body) : (null as T); 50 | } catch (error) { 51 | throw new Error('Invalid JSON'); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/runtime/src/progress/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Progress API - Clean refactored version with decorators 3 | * 4 | * Benefits: 5 | * - No duplication between implementation and metadata 6 | * - Types auto-detected from TypeScript signatures 7 | */ 8 | import { RuntimeAPI, RuntimeMethod } from '../metadata/decorators.js'; 9 | import { log } from '../log/index.js'; 10 | import type { ProgressCallback } from './types.js'; 11 | 12 | export type { ProgressCallback } from './types.js'; 13 | 14 | /** 15 | * Global progress callback (set by executor) 16 | */ 17 | let progressCallback: ProgressCallback | null = null; 18 | 19 | /** 20 | * Set the progress callback handler 21 | */ 22 | export function setProgressCallback(callback: ProgressCallback | null): void { 23 | progressCallback = callback; 24 | } 25 | 26 | /** 27 | * Progress Runtime API 28 | * 29 | * Allows reporting execution progress to clients 30 | */ 31 | @RuntimeAPI('progress', 'Progress API - Report execution progress to clients') 32 | class ProgressAPI { 33 | /** 34 | * Report progress with message and completion fraction 35 | */ 36 | @RuntimeMethod('Report progress with message and completion fraction', { 37 | message: { description: 'Progress message' }, 38 | fraction: { description: 'Completion fraction (0-1)' }, 39 | }) 40 | report(message: string, fraction: number): void { 41 | if (progressCallback) { 42 | try { 43 | progressCallback(message, fraction); 44 | } catch (error) { 45 | log.error('Progress callback error', { error }); 46 | } 47 | } 48 | } 49 | } 50 | 51 | export const progress = new ProgressAPI(); 52 | -------------------------------------------------------------------------------- /packages/langchain/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-langchain", 3 | "version": "0.20.7", 4 | "description": "LangChain integration for Agent Tool Protocol", 5 | "type": "module", 6 | "main": "./dist/index.cjs", 7 | "module": "./dist/index.js", 8 | "types": "./dist/index.d.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./dist/index.d.ts", 12 | "import": "./dist/index.js", 13 | "require": "./dist/index.cjs" 14 | } 15 | }, 16 | "files": [ 17 | "dist", 18 | "src" 19 | ], 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/mondaycom/agent-tool-protocol", 23 | "directory": "packages/langchain" 24 | }, 25 | "publishConfig": { 26 | "access": "public" 27 | }, 28 | "scripts": { 29 | "build": "npx tsc --build tsconfig.json && tsup", 30 | "build:tsc": "tsc -p tsconfig.json", 31 | "dev": "tsc -p tsconfig.json --watch", 32 | "clean": "rm -rf dist *.tsbuildinfo", 33 | "test": "vitest run", 34 | "lint": "tsc --noEmit" 35 | }, 36 | "keywords": [ 37 | "agent", 38 | "protocol", 39 | "atp", 40 | "langchain", 41 | "ai", 42 | "llm" 43 | ], 44 | "license": "MIT", 45 | "dependencies": { 46 | "@langchain/core": "^0.3.78", 47 | "@mondaydotcomorg/atp-client": "0.19.18", 48 | "@mondaydotcomorg/atp-protocol": "0.19.17", 49 | "@mondaydotcomorg/atp-runtime": "0.19.16", 50 | "json-schema-to-zod": "^2.6.1", 51 | "langchain": "^0.3.35" 52 | }, 53 | "peerDependencies": { 54 | "zod": "^3.25.0" 55 | }, 56 | "devDependencies": { 57 | "tsup": "^8.5.1", 58 | "typescript": "^5.3.3", 59 | "vitest": "^1.2.1", 60 | "zod": "^3.25.0" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/server/src/http/router.ts: -------------------------------------------------------------------------------- 1 | import type { RequestContext } from '../core/config.js'; 2 | import type { AgentToolProtocolServer } from '../create-server.js'; 3 | 4 | export async function handleRoute( 5 | ctx: RequestContext, 6 | server: AgentToolProtocolServer 7 | ): Promise { 8 | if (ctx.path === '/api/info' && ctx.method === 'GET') { 9 | ctx.responseBody = server.getInfo(); 10 | } else if (ctx.path === '/api/definitions' && ctx.method === 'GET') { 11 | ctx.responseBody = await server.getDefinitions(ctx); 12 | } else if (ctx.path === '/api/runtime' && ctx.method === 'GET') { 13 | ctx.responseBody = await server.getRuntimeDefinitions(ctx); 14 | } else if (ctx.path === '/api/init' && ctx.method === 'POST') { 15 | ctx.responseBody = await server.handleInit(ctx); 16 | } else if (ctx.path === '/api/search' && ctx.method === 'POST') { 17 | ctx.responseBody = await server.handleSearch(ctx); 18 | } else if (ctx.path.startsWith('/api/search') && ctx.method === 'GET') { 19 | ctx.responseBody = await server.handleSearchQuery(ctx); 20 | } else if (ctx.path === '/api/explore' && ctx.method === 'POST') { 21 | ctx.responseBody = await server.handleExplore(ctx); 22 | } else if (ctx.path === '/api/execute' && ctx.method === 'POST') { 23 | ctx.responseBody = await server.handleExecute(ctx); 24 | } else if (ctx.path.startsWith('/api/resume/') && ctx.method === 'POST') { 25 | const executionId = ctx.path.substring('/api/resume/'.length); 26 | ctx.responseBody = await server.handleResume(ctx, executionId); 27 | } else { 28 | ctx.status = 404; 29 | ctx.responseBody = { error: 'Not found' }; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/test-server/server.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Minimal ATP Test Server for LangChain Integration Testing 3 | */ 4 | import { config } from 'dotenv'; 5 | config({ path: '../../.env' }); 6 | 7 | // Set default JWT secret for development/testing if not provided 8 | if (!process.env.ATP_JWT_SECRET) { 9 | process.env.ATP_JWT_SECRET = 'test-key'; 10 | console.log( 11 | '⚠️ Using default JWT secret "test-key" for development. Set ATP_JWT_SECRET for production.' 12 | ); 13 | } 14 | 15 | import { AgentToolProtocolServer, loadOpenAPI } from '@mondaydotcomorg/atp-server'; 16 | 17 | async function main() { 18 | // Create ATP server 19 | const server = new AgentToolProtocolServer({ 20 | execution: { timeout: 30000 }, 21 | }); 22 | 23 | // Register tools 24 | server.tool('echo', { 25 | description: 'Echo back a message', 26 | input: { message: 'string' }, 27 | handler: async (params) => { 28 | const { message } = params as { message: string }; 29 | return { echoed: message, timestamp: Date.now() }; 30 | }, 31 | }); 32 | 33 | server.tool('add', { 34 | description: 'Add two numbers', 35 | input: { a: 'number', b: 'number' }, 36 | handler: async (params) => { 37 | const { a, b } = params as { a: number; b: number }; 38 | return { result: a + b }; 39 | }, 40 | }); 41 | 42 | await server.listen(3333); 43 | 44 | console.log('🚀 ATP Test Server started on http://localhost:3333'); 45 | console.log('📋 Available APIs: test.echo, test.add'); 46 | console.log('✨ Client services enabled (LLM & approval support)'); 47 | } 48 | 49 | main().catch((error) => { 50 | console.error('❌ Server error:', error); 51 | process.exit(1); 52 | }); 53 | -------------------------------------------------------------------------------- /packages/provenance/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-provenance", 3 | "version": "0.19.16", 4 | "description": "CAMEL-inspired provenance security for LLM applications - track data origin and enforce security policies", 5 | "main": "./dist/index.cjs", 6 | "module": "./dist/index.js", 7 | "types": "./dist/index.d.ts", 8 | "type": "module", 9 | "exports": { 10 | ".": { 11 | "types": "./dist/index.d.ts", 12 | "import": "./dist/index.js", 13 | "require": "./dist/index.cjs" 14 | } 15 | }, 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "files": [ 20 | "dist", 21 | "README.md" 22 | ], 23 | "scripts": { 24 | "build": "npx tsc --build tsconfig.json && tsup", 25 | "build:tsc": "tsc", 26 | "test": "jest", 27 | "lint": "tsc --noEmit", 28 | "clean": "rm -rf dist" 29 | }, 30 | "keywords": [ 31 | "provenance", 32 | "security", 33 | "atp", 34 | "llm", 35 | "prompt-injection", 36 | "camel", 37 | "agent", 38 | "capability-based-security" 39 | ], 40 | "author": "Agent Tool Protocol Team", 41 | "license": "MIT", 42 | "dependencies": { 43 | "@mondaydotcomorg/atp-runtime": "0.19.16", 44 | "@types/escodegen": "^0.0.10", 45 | "acorn": "^8.11.0", 46 | "acorn-walk": "^8.3.0", 47 | "escodegen": "^2.1.0" 48 | }, 49 | "peerDependencies": { 50 | "zod": "^3.25.0" 51 | }, 52 | "devDependencies": { 53 | "@types/node": "^20.10.0", 54 | "tsup": "^8.5.1", 55 | "typescript": "^5.3.0", 56 | "zod": "^3.25.0" 57 | }, 58 | "repository": { 59 | "type": "git", 60 | "url": "https://github.com/mondaycom/agent-tool-protocol", 61 | "directory": "packages/provenance" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /packages/client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-client", 3 | "version": "0.19.18", 4 | "description": "Client SDK for Agent Tool Protocol", 5 | "type": "module", 6 | "main": "./dist/index.cjs", 7 | "module": "./dist/index.js", 8 | "types": "./dist/index.d.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./dist/index.d.ts", 12 | "import": "./dist/index.js", 13 | "require": "./dist/index.cjs" 14 | }, 15 | "./core": { 16 | "types": "./dist/core/index.d.ts", 17 | "import": "./dist/core/index.js", 18 | "require": "./dist/core/index.cjs" 19 | } 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "https://github.com/mondaycom/agent-tool-protocol", 24 | "directory": "packages/client" 25 | }, 26 | "files": [ 27 | "dist", 28 | "src" 29 | ], 30 | "scripts": { 31 | "build": "npx tsc --build tsconfig.json && tsup", 32 | "build:tsc": "tsc -p tsconfig.json", 33 | "dev": "tsc -p tsconfig.json --watch", 34 | "clean": "rm -rf dist *.tsbuildinfo", 35 | "test": "vitest run", 36 | "lint": "tsc --noEmit" 37 | }, 38 | "keywords": [ 39 | "agent", 40 | "protocol", 41 | "client", 42 | "atp", 43 | "ai", 44 | "llm" 45 | ], 46 | "publishConfig": { 47 | "access": "public" 48 | }, 49 | "license": "MIT", 50 | "dependencies": { 51 | "@mondaydotcomorg/atp-protocol": "0.19.17", 52 | "@mondaydotcomorg/atp-runtime": "0.19.16", 53 | "undici": "*", 54 | "zod-to-json-schema": "^3.24.6" 55 | }, 56 | "peerDependencies": { 57 | "zod": "^3.25.0" 58 | }, 59 | "devDependencies": { 60 | "tsup": "^8.5.1", 61 | "typescript": "^5.3.3", 62 | "vitest": "^1.2.1", 63 | "zod": "^3.25.0" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /examples/langchain-quickstart/index.ts: -------------------------------------------------------------------------------- 1 | import { createServer, loadOpenAPI } from '@mondaydotcomorg/atp-server'; 2 | import { ChatOpenAI } from '@langchain/openai'; 3 | import { createReactAgent } from '@langchain/langgraph/prebuilt'; 4 | import { createATPTools } from '@mondaydotcomorg/atp-langchain'; 5 | 6 | process.env.ATP_JWT_SECRET = process.env.ATP_JWT_SECRET || 'test-secret-key'; 7 | 8 | async function startServer() { 9 | const server = createServer({}); 10 | 11 | const petstore = await loadOpenAPI('https://petstore.swagger.io/v2/swagger.json', { 12 | name: 'petstore', 13 | filter: { methods: ['GET'] }, 14 | }); 15 | 16 | server.use([petstore]); 17 | await server.listen(3333); 18 | console.log('ATP Server started on http://localhost:3333\n'); 19 | } 20 | 21 | async function runAgent() { 22 | const llm = new ChatOpenAI({ modelName: 'gpt-4o-mini', temperature: 0 }); 23 | 24 | const { tools } = await createATPTools({ 25 | serverUrl: 'http://localhost:3333', 26 | llm, 27 | }); 28 | 29 | const agent = createReactAgent({ llm, tools }); 30 | 31 | console.log('Running agent...\n'); 32 | 33 | const result = await agent.invoke({ 34 | messages: [ 35 | { 36 | role: 'user', 37 | content: 38 | 'Use ATP to fetch available pets from the petstore API, then tell me how many pets are available and list 3 example pet names.', 39 | }, 40 | ], 41 | }); 42 | 43 | const lastMessage = result.messages[result.messages.length - 1]; 44 | console.log('Agent response:', lastMessage.content); 45 | } 46 | 47 | async function main() { 48 | await startServer(); 49 | await runAgent(); 50 | process.exit(0); 51 | } 52 | 53 | main().catch(console.error); 54 | -------------------------------------------------------------------------------- /packages/vercel-ai-sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-vercel-sdk", 3 | "version": "0.20.7", 4 | "description": "Vercel AI SDK integration for Agent Tool Protocol", 5 | "type": "module", 6 | "main": "./dist/index.cjs", 7 | "module": "./dist/index.js", 8 | "types": "./dist/index.d.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./dist/index.d.ts", 12 | "import": "./dist/index.js", 13 | "require": "./dist/index.cjs" 14 | } 15 | }, 16 | "files": [ 17 | "dist", 18 | "src" 19 | ], 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/mondaycom/agent-tool-protocol", 23 | "directory": "packages/vercel-ai-sdk" 24 | }, 25 | "publishConfig": { 26 | "access": "public" 27 | }, 28 | "scripts": { 29 | "build": "npx tsc --build tsconfig.json && tsup", 30 | "build:tsc": "tsc -p tsconfig.json", 31 | "dev": "tsc -p tsconfig.json --watch", 32 | "clean": "rm -rf dist *.tsbuildinfo", 33 | "test": "NODE_OPTIONS='--no-node-snapshot' jest --runInBand --forceExit --testTimeout=30000", 34 | "lint": "tsc --noEmit" 35 | }, 36 | "keywords": [ 37 | "agent", 38 | "protocol", 39 | "atp", 40 | "vercel", 41 | "ai-sdk", 42 | "ai", 43 | "llm" 44 | ], 45 | "license": "MIT", 46 | "dependencies": { 47 | "@mondaydotcomorg/atp-client": "0.19.18", 48 | "@mondaydotcomorg/atp-protocol": "0.19.17" 49 | }, 50 | "peerDependencies": { 51 | "ai": "^5.0.0", 52 | "zod": "^3.25.0" 53 | }, 54 | "devDependencies": { 55 | "@jest/globals": "^29.7.0", 56 | "@types/jest": "^29.5.11", 57 | "ai": "^5.0.0", 58 | "jest": "^29.7.0", 59 | "tsup": "^8.5.1", 60 | "typescript": "^5.3.3", 61 | "zod": "^3.25.0" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /packages/mcp-adapter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-mcp-adapter", 3 | "version": "0.20.6", 4 | "description": "MCP compatibility adapter for Agent Tool Protocol", 5 | "type": "module", 6 | "main": "./dist/index.cjs", 7 | "module": "./dist/index.js", 8 | "types": "./dist/index.d.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./dist/index.d.ts", 12 | "import": "./dist/index.js", 13 | "require": "./dist/index.cjs" 14 | } 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/mondaycom/agent-tool-protocol", 19 | "directory": "packages/mcp-adapter" 20 | }, 21 | "files": [ 22 | "dist", 23 | "src" 24 | ], 25 | "publishConfig": { 26 | "access": "public" 27 | }, 28 | "scripts": { 29 | "build": "npx tsc --build tsconfig.json && tsup", 30 | "build:tsc": "tsc -p tsconfig.json", 31 | "dev": "tsc -p tsconfig.json --watch", 32 | "clean": "rm -rf dist *.tsbuildinfo", 33 | "test": "vitest run", 34 | "lint": "tsc --noEmit" 35 | }, 36 | "keywords": [ 37 | "agent", 38 | "protocol", 39 | "atp", 40 | "mcp", 41 | "adapter", 42 | "ai", 43 | "llm" 44 | ], 45 | "license": "MIT", 46 | "dependencies": { 47 | "@mondaydotcomorg/atp-protocol": "0.19.17", 48 | "@mondaydotcomorg/atp-server": "0.20.5" 49 | }, 50 | "peerDependencies": { 51 | "@modelcontextprotocol/sdk": ">=0.5.0", 52 | "zod": "^3.25.0" 53 | }, 54 | "peerDependenciesMeta": { 55 | "@modelcontextprotocol/sdk": { 56 | "optional": true 57 | } 58 | }, 59 | "devDependencies": { 60 | "@modelcontextprotocol/sdk": "^1.23.0", 61 | "tsup": "^8.5.1", 62 | "typescript": "^5.3.3", 63 | "vitest": "^1.2.1", 64 | "zod": "^3.25.0" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /examples/quickstart/index.ts: -------------------------------------------------------------------------------- 1 | import { createServer, loadOpenAPI } from '@mondaydotcomorg/atp-server'; 2 | import { AgentToolProtocolClient } from '@mondaydotcomorg/atp-client'; 3 | import { MCPConnector } from '@mondaydotcomorg/atp-mcp-adapter'; 4 | 5 | process.env.ATP_JWT_SECRET = process.env.ATP_JWT_SECRET || 'test-secret-key'; 6 | process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; 7 | 8 | async function main() { 9 | const server = createServer({}); 10 | 11 | const petstore = await loadOpenAPI('https://petstore.swagger.io/v2/swagger.json', { 12 | name: 'petstore', 13 | filter: { methods: ['GET'] }, 14 | }); 15 | 16 | const mcpConnector = new MCPConnector(); 17 | const playwright = await mcpConnector.connectToMCPServer({ 18 | name: 'playwright', 19 | command: 'npx', 20 | args: ['@playwright/mcp@latest'], 21 | }); 22 | 23 | server.use([petstore, playwright]); 24 | await server.listen(3333); 25 | 26 | const client = new AgentToolProtocolClient({ 27 | baseUrl: 'http://localhost:3333', 28 | }); 29 | await client.init({ name: 'quickstart', version: '1.0.0' }); 30 | 31 | const result = await client.execute(` 32 | const pets = await api.petstore.findPetsByStatus({ status: 'available' }); 33 | 34 | const categories = pets 35 | .filter(p => p.category?.name) 36 | .map(p => p.category.name) 37 | .filter((v, i, a) => a.indexOf(v) === i); 38 | 39 | return { 40 | totalPets: pets.length, 41 | categories: categories.slice(0, 5), 42 | sample: pets.slice(0, 3).map(p => ({ 43 | name: p.name, 44 | status: p.status 45 | })) 46 | }; 47 | `); 48 | 49 | console.log('Result:', JSON.stringify(result.result, null, 2)); 50 | process.exit(0); 51 | } 52 | 53 | main().catch(console.error); 54 | -------------------------------------------------------------------------------- /packages/langchain/src/node.ts: -------------------------------------------------------------------------------- 1 | import { AgentToolProtocolClient } from '@mondaydotcomorg/atp-client'; 2 | import { ExecutionStatus } from '@mondaydotcomorg/atp-protocol'; 3 | 4 | /** 5 | * LangGraph-compatible node for ATP execution 6 | */ 7 | export class ATPExecutionNode { 8 | private client: AgentToolProtocolClient; 9 | 10 | constructor(client: AgentToolProtocolClient) { 11 | this.client = client; 12 | } 13 | 14 | /** 15 | * Execute code from the state and update the state with results 16 | */ 17 | async execute(state: { code?: string; messages?: any[]; [key: string]: any }): Promise { 18 | if (!state.code) { 19 | throw new Error('No code provided in state'); 20 | } 21 | 22 | const result = await this.client.execute(state.code); 23 | 24 | return { 25 | ...state, 26 | executionResult: result, 27 | lastExecutionStatus: result.status, 28 | lastExecutionOutput: 29 | result.status === ExecutionStatus.COMPLETED ? result.result : result.error, 30 | }; 31 | } 32 | 33 | /** 34 | * Create a function suitable for LangGraph node 35 | */ 36 | asFunction() { 37 | return this.execute.bind(this); 38 | } 39 | } 40 | 41 | /** 42 | * Helper to create a simple ATP execution node function 43 | */ 44 | export function createATPNode(client: AgentToolProtocolClient) { 45 | return async (state: any) => { 46 | if (!state.code) { 47 | throw new Error('No code provided in state'); 48 | } 49 | 50 | const result = await client.execute(state.code); 51 | 52 | return { 53 | ...state, 54 | executionResult: result, 55 | lastExecutionStatus: result.status, 56 | lastExecutionOutput: 57 | result.status === ExecutionStatus.COMPLETED ? result.result : result.error, 58 | }; 59 | }; 60 | } 61 | -------------------------------------------------------------------------------- /packages/runtime/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-runtime", 3 | "version": "0.19.16", 4 | "description": "Runtime SDK injected into sandbox for Agent Tool Protocol", 5 | "type": "module", 6 | "main": "./dist/index.cjs", 7 | "module": "./dist/index.js", 8 | "types": "./dist/index.d.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./dist/index.d.ts", 12 | "import": "./dist/index.js", 13 | "require": "./dist/index.cjs" 14 | } 15 | }, 16 | "files": [ 17 | "dist", 18 | "src" 19 | ], 20 | "publishConfig": { 21 | "access": "public" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/mondaycom/agent-tool-protocol", 26 | "directory": "packages/runtime" 27 | }, 28 | "scripts": { 29 | "build": "npm run generate:metadata && npx tsc --build tsconfig.json && tsup", 30 | "build:tsc": "npm run generate:metadata && tsc -p tsconfig.json", 31 | "generate:metadata": "tsx scripts/generate-metadata.ts", 32 | "dev": "tsc -p tsconfig.json --watch", 33 | "clean": "rm -rf dist *.tsbuildinfo src/metadata/generated.ts", 34 | "test": "vitest run", 35 | "lint": "tsc --noEmit" 36 | }, 37 | "keywords": [ 38 | "agent", 39 | "protocol", 40 | "atp", 41 | "runtime", 42 | "sdk", 43 | "ai", 44 | "llm" 45 | ], 46 | "license": "MIT", 47 | "dependencies": { 48 | "ioredis": "^5.8.0", 49 | "node-cache": "*", 50 | "pino": "*", 51 | "pino-pretty": "*", 52 | "reflect-metadata": "^0.2.1", 53 | "undici": "*" 54 | }, 55 | "devDependencies": { 56 | "@types/node": "^20.11.5", 57 | "ts-json-schema-generator": "^2.4.0", 58 | "ts-morph": "^21.0.1", 59 | "tsup": "^8.5.1", 60 | "tsx": "^4.7.0", 61 | "typescript": "^5.3.3", 62 | "vitest": "^1.2.1" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /__tests__/README.md: -------------------------------------------------------------------------------- 1 | # Test Suite Documentation 2 | 3 | This directory contains the Jest test suite for the Agent Tool Protocol. 4 | 5 | ## Structure 6 | 7 | - **`__tests__/unit/`** - Unit tests for individual components 8 | - `runtime.test.ts` - Tests for HTTP client, cache, and logging 9 | - `executor.test.ts` - Tests for sandbox code execution 10 | - `search.test.ts` - Tests for API function search engine 11 | - `serializer.test.ts` - Tests for function serialization with closures 12 | - `serializer-dynamic.test.ts` - Tests for dynamic serializer features 13 | - `mcp-optional-fields.test.ts` - Tests for MCP schema optional field handling 14 | - `aggregator-optional-fields.test.ts` - Tests for TypeScript generation with optional fields 15 | 16 | - **`__tests__/e2e/`** - End-to-end integration tests 17 | - `server.test.ts` - Full ATP server integration tests 18 | 19 | ## Running Tests 20 | 21 | ```bash 22 | # Run all tests 23 | yarn test 24 | 25 | # Run unit tests only 26 | yarn test:unit 27 | 28 | # Run E2E tests only 29 | yarn test:e2e 30 | 31 | # Run tests in watch mode 32 | yarn test:watch 33 | 34 | # Run tests with coverage 35 | yarn test:coverage 36 | ``` 37 | 38 | ## Test Configuration 39 | 40 | The test suite uses: 41 | 42 | - **Jest** - Test framework 43 | - **ts-jest** - TypeScript transformation 44 | - **@jest/globals** - Modern Jest API 45 | - Custom resolver for `.js` to `.ts` mapping 46 | 47 | Configuration is in `jest.config.js` at the project root. 48 | 49 | ## Notes 50 | 51 | - One HTTP POST test is skipped due to external API certificate issues 52 | - E2E tests start an actual server on port 3334 53 | - Tests use in-memory cache (no external dependencies) 54 | - LLM calls are not executed in tests (no API keys required) 55 | -------------------------------------------------------------------------------- /packages/atp-compiler/src/plugin-system/default-plugins/array-transformer-plugin.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Default Array Transformer Plugin 3 | * Wraps the existing ArrayTransformer 4 | */ 5 | 6 | import * as t from '@babel/types'; 7 | import type { TransformationPlugin, BabelVisitor } from '../plugin-api.js'; 8 | import type { CompilerConfig, TransformMetadata } from '../../types.js'; 9 | import { ArrayTransformer } from '../../transformer/array-transformer.js'; 10 | 11 | export class DefaultArrayTransformerPlugin implements TransformationPlugin { 12 | name = 'atp-array-transformer'; 13 | version = '1.0.0'; 14 | priority = 100; 15 | 16 | private transformer: ArrayTransformer; 17 | 18 | constructor(batchSizeThreshold?: number) { 19 | this.transformer = new ArrayTransformer(batchSizeThreshold); 20 | } 21 | 22 | getVisitor(config: CompilerConfig): BabelVisitor { 23 | return { 24 | CallExpression: (path: any) => { 25 | const node = path.node; 26 | if (this.isArrayMethodCall(node)) { 27 | this.transformer.transformArrayMethod(path); 28 | } 29 | }, 30 | }; 31 | } 32 | 33 | getMetadata(): Partial { 34 | return { 35 | arrayMethodCount: this.transformer.getTransformCount(), 36 | }; 37 | } 38 | 39 | reset(): void { 40 | this.transformer.resetTransformCount(); 41 | } 42 | 43 | private isArrayMethodCall(node: t.CallExpression): boolean { 44 | if (!t.isMemberExpression(node.callee)) { 45 | return false; 46 | } 47 | 48 | const property = node.callee.property; 49 | if (!t.isIdentifier(property)) { 50 | return false; 51 | } 52 | 53 | const arrayMethods = ['map', 'forEach', 'filter', 'reduce', 'find', 'some', 'every', 'flatMap']; 54 | return arrayMethods.includes(property.name); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /examples/vercel-ai-sdk-example/streaming.ts: -------------------------------------------------------------------------------- 1 | import 'dotenv/config'; 2 | import { createATPTools } from '@mondaydotcomorg/atp-vercel-sdk'; 3 | import { openai } from '@ai-sdk/openai'; 4 | import { streamText } from 'ai'; 5 | 6 | async function main() { 7 | const model = openai('gpt-4o-mini'); 8 | 9 | const { tools } = await createATPTools({ 10 | serverUrl: process.env.ATP_SERVER_URL || 'http://localhost:3333', 11 | headers: { 12 | Authorization: `Bearer ${process.env.ATP_API_KEY || 'test-key'}`, 13 | }, 14 | model, 15 | approvalHandler: async (message) => { 16 | console.log('\n🔔 Auto-approving:', message); 17 | return true; 18 | }, 19 | }); 20 | 21 | console.log('✅ ATP Client connected with streaming support'); 22 | console.log('📋 Available tools:', Object.keys(tools).join(', ')); 23 | 24 | const prompt = `Use ATP to execute code that calls atp.llm.call() to write a short story about a robot learning to paint. Then return the story.`; 25 | 26 | console.log('\n🤖 Streaming agent response...\n'); 27 | 28 | const result = await streamText({ 29 | model, 30 | system: `You are a helpful assistant with access to ATP (Agent Tool Protocol). 31 | You can execute TypeScript code using the atp_execute_code tool. 32 | Within the code, you have access to atp.llm.call() to make LLM calls.`, 33 | prompt, 34 | tools, 35 | maxSteps: 5, 36 | }); 37 | 38 | for await (const chunk of result.textStream) { 39 | process.stdout.write(chunk); 40 | } 41 | 42 | console.log('\n\n✅ Streaming complete!'); 43 | 44 | const fullResult = await result.response; 45 | console.log('\n📊 Final result:', fullResult); 46 | 47 | process.exit(0); 48 | } 49 | 50 | main().catch((error) => { 51 | console.error('❌ Error:', error); 52 | process.exit(1); 53 | }); 54 | -------------------------------------------------------------------------------- /packages/server/src/executor/resume-handler.ts: -------------------------------------------------------------------------------- 1 | import type { Logger } from '@mondaydotcomorg/atp-runtime'; 2 | import { setReplayMode, setAPIResultCache } from '@mondaydotcomorg/atp-runtime'; 3 | import type { CallbackRecord } from '../execution-state/index.js'; 4 | 5 | export interface ResumeData { 6 | callbackHistory: CallbackRecord[]; 7 | newCallbackResult: unknown; 8 | executionId?: string; 9 | } 10 | 11 | export function setupResumeExecution( 12 | resumeData: ResumeData, 13 | callbackHistory: CallbackRecord[], 14 | executionLogger: Logger 15 | ): void { 16 | executionLogger.info('Resuming execution with callback history', { 17 | historyLength: resumeData.callbackHistory.length, 18 | }); 19 | 20 | const replayMap = new Map(); 21 | const apiCache = new Map(); 22 | 23 | for (const record of resumeData.callbackHistory) { 24 | if (record.result !== undefined) { 25 | replayMap.set(record.sequenceNumber, record.result); 26 | if ( 27 | record.operation && 28 | record.operation.includes('.') && 29 | !record.operation.includes('call') 30 | ) { 31 | const cacheKey = `${record.operation}:${JSON.stringify(record.payload)}`; 32 | apiCache.set(cacheKey, record.result); 33 | } 34 | } 35 | } 36 | 37 | const lastCallback = resumeData.callbackHistory[resumeData.callbackHistory.length - 1]; 38 | if (lastCallback) { 39 | replayMap.set(lastCallback.sequenceNumber, resumeData.newCallbackResult); 40 | } 41 | 42 | setReplayMode(replayMap); 43 | 44 | if (apiCache.size > 0) { 45 | setAPIResultCache(apiCache); 46 | } 47 | 48 | callbackHistory.push(...resumeData.callbackHistory); 49 | 50 | executionLogger.debug('Replay map configured', { 51 | replayEntries: replayMap.size, 52 | }); 53 | } 54 | -------------------------------------------------------------------------------- /packages/protocol/src/schemas.ts: -------------------------------------------------------------------------------- 1 | import type { JSONSchema } from './types.js'; 2 | 3 | export const ExecutionConfigSchema: JSONSchema = { 4 | type: 'object', 5 | properties: { 6 | timeout: { type: 'number', minimum: 1000, maximum: 300000 }, 7 | maxMemory: { type: 'number', minimum: 1048576, maximum: 536870912 }, 8 | maxLLMCalls: { type: 'number', minimum: 0, maximum: 100 }, 9 | allowedAPIs: { type: 'array', items: { type: 'string' } }, 10 | allowLLMCalls: { type: 'boolean' }, 11 | }, 12 | required: ['timeout', 'maxMemory', 'maxLLMCalls', 'allowedAPIs', 'allowLLMCalls'], 13 | }; 14 | 15 | export const SearchOptionsSchema: JSONSchema = { 16 | type: 'object', 17 | properties: { 18 | query: { type: 'string', minLength: 1 }, 19 | apiGroups: { type: 'array', items: { type: 'string' } }, 20 | maxResults: { type: 'number', minimum: 1, maximum: 100 }, 21 | useEmbeddings: { type: 'boolean' }, 22 | embeddingModel: { type: 'string' }, 23 | }, 24 | required: ['query'], 25 | }; 26 | 27 | export const AgentToolProtocolRequestSchema: JSONSchema = { 28 | type: 'object', 29 | properties: { 30 | jsonrpc: { type: 'string', enum: ['2.0'] }, 31 | id: { type: ['string', 'number'] }, 32 | method: { type: 'string' }, 33 | params: { type: 'object' }, 34 | }, 35 | required: ['jsonrpc', 'id', 'method', 'params'], 36 | }; 37 | 38 | export const AgentToolProtocolResponseSchema: JSONSchema = { 39 | type: 'object', 40 | properties: { 41 | jsonrpc: { type: 'string', enum: ['2.0'] }, 42 | id: { type: ['string', 'number'] }, 43 | result: {}, 44 | error: { 45 | type: 'object', 46 | properties: { 47 | code: { type: 'number' }, 48 | message: { type: 'string' }, 49 | data: {}, 50 | }, 51 | required: ['code', 'message'], 52 | }, 53 | }, 54 | required: ['jsonrpc', 'id'], 55 | }; 56 | -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/nx/schemas/nx-schema.json", 3 | "targetDefaults": { 4 | "build": { 5 | "dependsOn": ["^build"], 6 | "outputs": ["{projectRoot}/dist"], 7 | "cache": true 8 | }, 9 | "test": { 10 | "dependsOn": ["build"], 11 | "outputs": ["{projectRoot}/coverage"], 12 | "cache": true 13 | }, 14 | "lint": { 15 | "cache": true 16 | }, 17 | "clean": { 18 | "cache": false 19 | }, 20 | "dev": { 21 | "cache": false 22 | }, 23 | "nx-release-publish": { 24 | "dependsOn": ["build"] 25 | } 26 | }, 27 | "namedInputs": { 28 | "default": ["{projectRoot}/**/*", "sharedGlobals"], 29 | "production": [ 30 | "default", 31 | "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)", 32 | "!{projectRoot}/tsconfig.spec.json", 33 | "!{projectRoot}/.eslintrc.json" 34 | ], 35 | "sharedGlobals": ["{workspaceRoot}/tsconfig.json"] 36 | }, 37 | "release": { 38 | "projects": ["packages/*"], 39 | "projectsRelationship": "independent", 40 | "version": { 41 | "conventionalCommits": true, 42 | "fallbackCurrentVersionResolver": "disk", 43 | "git": { 44 | "commit": true, 45 | "commitMessage": "chore(release): atp-publish", 46 | "tag": true, 47 | "tagMessage": "{projectName}@{version}", 48 | "push": true 49 | } 50 | } 51 | }, 52 | "plugins": [ 53 | { 54 | "plugin": "@nx/js", 55 | "options": { 56 | "analyzeSourceFiles": true 57 | } 58 | }, 59 | { 60 | "plugin": "@nx/js/typescript", 61 | "options": { 62 | "typecheck": { 63 | "targetName": "typecheck" 64 | }, 65 | "build": { 66 | "targetName": "build", 67 | "configName": "tsconfig.lib.json", 68 | "buildDepsName": "build-deps", 69 | "watchDepsName": "watch-deps" 70 | } 71 | } 72 | } 73 | ], 74 | "defaultProject": "protocol" 75 | } 76 | -------------------------------------------------------------------------------- /examples/production-example/README.md: -------------------------------------------------------------------------------- 1 | # Production Example 2 | 3 | Complete production setup with: 4 | 5 | - Dependency injection (cache, auth, audit) 6 | - Security middleware (CORS, rate limiting, API keys) 7 | - Client session management 8 | - OpenAPI loading 9 | - Custom tools 10 | 11 | ## Setup 12 | 13 | ```bash 14 | # Set API keys (optional) 15 | export ATP_API_KEYS="key1,key2,key3" 16 | 17 | # Run 18 | tsx server.ts 19 | ``` 20 | 21 | ## Features 22 | 23 | ### Provider Injection 24 | 25 | - **Cache**: MemoryCache (use RedisCache in production) 26 | - **Auth**: EnvAuthProvider (use AWSSecretsAuthProvider in production) 27 | - **Audit**: JSONLAuditSink (use PostgresAuditSink in production) 28 | 29 | ### Middleware 30 | 31 | - **CORS**: Allow all origins 32 | - **Rate Limiting**: 100/hour global, 50/hour for execute 33 | - **API Key Auth**: Optional authentication 34 | 35 | ### Client Sessions 36 | 37 | - Enabled with 1h TTL 38 | - Token rotation every 30min 39 | - Requires cache provider 40 | 41 | ## Test 42 | 43 | ```bash 44 | # Initialize client 45 | curl -X POST http://localhost:3000/api/init \ 46 | -H "Content-Type: application/json" \ 47 | -d '{"clientInfo": {"name": "my-app", "version": "1.0.0"}}' 48 | 49 | # Get definitions 50 | curl http://localhost:3000/api/definitions 51 | 52 | # View audit log 53 | cat audit.jsonl 54 | ``` 55 | 56 | ## Production Deployment 57 | 58 | Replace providers with production-grade alternatives: 59 | 60 | ```typescript 61 | import { 62 | RedisCache, 63 | PostgresAuditSink, 64 | AWSSecretsAuthProvider, 65 | } from '@mondaydotcomorg/atp-providers'; 66 | 67 | server.setCache(new RedisCache({ url: process.env.REDIS_URL })); 68 | server.setAudit(new PostgresAuditSink({ connectionString: process.env.DATABASE_URL })); 69 | server.setAuthProvider(new AWSSecretsAuthProvider({ region: 'us-east-1' })); 70 | ``` 71 | -------------------------------------------------------------------------------- /packages/providers/src/auth/env.ts: -------------------------------------------------------------------------------- 1 | import type { AuthProvider } from '@mondaydotcomorg/atp-protocol'; 2 | 3 | /** 4 | * Environment variable based auth provider 5 | * Simple provider that reads credentials from process.env 6 | * Good for development and simple deployments 7 | */ 8 | export class EnvAuthProvider implements AuthProvider { 9 | name = 'env'; 10 | private prefix: string; 11 | private credentials: Map; 12 | 13 | constructor( 14 | options: { 15 | prefix?: string; 16 | credentials?: Record; 17 | } = {} 18 | ) { 19 | this.prefix = options.prefix || 'ATP_'; 20 | this.credentials = new Map(); 21 | 22 | if (options.credentials) { 23 | for (const [key, value] of Object.entries(options.credentials)) { 24 | this.credentials.set(key, value); 25 | } 26 | } 27 | } 28 | 29 | async getCredential(key: string): Promise { 30 | if (this.credentials.has(key)) { 31 | return this.credentials.get(key) || null; 32 | } 33 | 34 | const envValue = process.env[key] || process.env[`${this.prefix}${key}`]; 35 | return envValue || null; 36 | } 37 | 38 | async setCredential(key: string, value: string, _ttl?: number): Promise { 39 | this.credentials.set(key, value); 40 | } 41 | 42 | async deleteCredential(key: string): Promise { 43 | this.credentials.delete(key); 44 | } 45 | 46 | async listCredentials(): Promise { 47 | const keys = new Set(); 48 | 49 | for (const key of this.credentials.keys()) { 50 | keys.add(key); 51 | } 52 | 53 | for (const key of Object.keys(process.env)) { 54 | if (key.startsWith(this.prefix)) { 55 | keys.add(key.substring(this.prefix.length)); 56 | } 57 | } 58 | 59 | return Array.from(keys); 60 | } 61 | 62 | async disconnect(): Promise { 63 | this.credentials.clear(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /packages/server/src/instrumentation/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Types for code instrumentation and state capture system 3 | */ 4 | 5 | export interface InstrumentationMetadata { 6 | statements: StatementMetadata[]; 7 | variables: Set; 8 | functions: FunctionMetadata[]; 9 | } 10 | 11 | export interface StatementMetadata { 12 | id: number; 13 | line?: number; 14 | type: string; 15 | } 16 | 17 | export interface FunctionMetadata { 18 | name: string; 19 | line?: number; 20 | } 21 | 22 | export interface InstrumentedCode { 23 | code: string; 24 | sourceMap?: any; 25 | metadata: InstrumentationMetadata; 26 | } 27 | 28 | export interface SerializedValue { 29 | type: 30 | | 'primitive' 31 | | 'object' 32 | | 'array' 33 | | 'function' 34 | | 'date' 35 | | 'regexp' 36 | | 'map' 37 | | 'set' 38 | | 'circular' 39 | | 'nonserializable'; 40 | value?: unknown; 41 | className?: string; 42 | properties?: Record; 43 | source?: string; 44 | closure?: Record; 45 | isAsync?: boolean; 46 | isGenerator?: boolean; 47 | isArrow?: boolean; 48 | pattern?: string; 49 | flags?: string; 50 | entries?: Array<[SerializedValue, SerializedValue]>; 51 | items?: SerializedValue[]; 52 | refId?: string; 53 | } 54 | 55 | export interface ExecutionState { 56 | executionId: string; 57 | clientId: string; 58 | currentStatementId: number; 59 | statements: Array<[number, StatementState]>; 60 | variables: Array<[string, SerializedValue]>; 61 | controlFlow: BranchDecision[]; 62 | } 63 | 64 | export interface StatementState { 65 | id: number; 66 | executed: boolean; 67 | variables: Record; 68 | result?: SerializedValue; 69 | timestamp: number; 70 | } 71 | 72 | export interface BranchDecision { 73 | statementId: number; 74 | taken: boolean; 75 | timestamp: number; 76 | } 77 | -------------------------------------------------------------------------------- /examples/runtime-openapi-loading/server.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Runtime OpenAPI Loading Example 3 | * Shows how to load OpenAPI specs dynamically after the server has started 4 | */ 5 | 6 | import { createServer } from '@mondaydotcomorg/atp-server'; 7 | 8 | const server = createServer(); 9 | 10 | // Start the server first 11 | await server.listen(3000); 12 | console.log('✨ Server started on port 3000'); 13 | 14 | // Now you can load OpenAPI specs dynamically at runtime 15 | // The same use() method works both before AND after server starts! 16 | console.log('\n📚 Loading OpenAPI spec at runtime...'); 17 | 18 | try { 19 | // Load from URL - same method whether server is running or not 20 | await server.loadOpenAPI('http://localhost:3040/openapi.json', { 21 | name: 'demo', 22 | // Optional: filter which operations to include 23 | filter: { 24 | methods: ['GET', 'POST'], 25 | // tags: ['pets'], 26 | }, 27 | }); 28 | 29 | console.log('✅ OpenAPI spec loaded successfully!'); 30 | } catch (error) { 31 | console.error('❌ Failed to load OpenAPI spec:', error); 32 | } 33 | 34 | // You can also add custom API groups at runtime using the same use() method 35 | const customGroup = { 36 | name: 'custom', 37 | type: 'custom' as const, 38 | functions: [ 39 | { 40 | name: 'sayHello', 41 | description: 'Say hello', 42 | inputSchema: { 43 | type: 'object', 44 | properties: { 45 | name: { type: 'string' }, 46 | }, 47 | required: ['name'], 48 | }, 49 | handler: async (input: any) => { 50 | return { message: `Hello ${input.name}!` }; 51 | }, 52 | }, 53 | ], 54 | }; 55 | 56 | // Same use() method - automatically handles runtime vs pre-start 57 | server.use(customGroup); 58 | console.log('✅ Custom API group added!'); 59 | 60 | console.log('\n🚀 Ready to accept requests!'); 61 | console.log(' Try: curl http://localhost:3000/atp/definitions'); 62 | -------------------------------------------------------------------------------- /packages/atp-compiler/src/runtime/resumable-parallel.ts: -------------------------------------------------------------------------------- 1 | import { getCheckpointManager } from './checkpoint-manager.js'; 2 | import type { LoopCheckpoint } from '../types.js'; 3 | 4 | export async function resumablePromiseAll( 5 | promises: Promise[], 6 | parallelId: string 7 | ): Promise { 8 | const checkpointManager = getCheckpointManager(); 9 | const checkpoint = await checkpointManager.load(parallelId); 10 | const startIndex = checkpoint?.currentIndex || 0; 11 | const results = (checkpoint?.results as T[]) || []; 12 | 13 | for (let i = startIndex; i < promises.length; i++) { 14 | results[i] = (await promises[i]) as T; 15 | 16 | const newCheckpoint: LoopCheckpoint = { 17 | loopId: parallelId, 18 | currentIndex: i + 1, 19 | results: results, 20 | timestamp: Date.now(), 21 | }; 22 | await checkpointManager.save(newCheckpoint); 23 | } 24 | 25 | await checkpointManager.clear(parallelId); 26 | return results; 27 | } 28 | 29 | export async function resumablePromiseAllSettled( 30 | promises: Promise[], 31 | parallelId: string 32 | ): Promise[]> { 33 | const checkpointManager = getCheckpointManager(); 34 | const checkpoint = await checkpointManager.load(parallelId); 35 | const startIndex = checkpoint?.currentIndex || 0; 36 | const results = (checkpoint?.results as PromiseSettledResult[]) || []; 37 | 38 | for (let i = startIndex; i < promises.length; i++) { 39 | try { 40 | const value = (await promises[i]) as T; 41 | results[i] = { status: 'fulfilled', value }; 42 | } catch (reason) { 43 | results[i] = { status: 'rejected', reason }; 44 | } 45 | 46 | const newCheckpoint: LoopCheckpoint = { 47 | loopId: parallelId, 48 | currentIndex: i + 1, 49 | results: results, 50 | timestamp: Date.now(), 51 | }; 52 | await checkpointManager.save(newCheckpoint); 53 | } 54 | 55 | await checkpointManager.clear(parallelId); 56 | return results; 57 | } 58 | -------------------------------------------------------------------------------- /packages/server/src/handlers/init.handler.ts: -------------------------------------------------------------------------------- 1 | import type { RequestContext } from '../core/config.js'; 2 | import type { ClientSessionManager } from '../client-sessions.js'; 3 | import type { AuditSink, AuditEvent } from '@mondaydotcomorg/atp-protocol'; 4 | import { randomUUID } from 'node:crypto'; 5 | import { log } from '@mondaydotcomorg/atp-runtime'; 6 | 7 | export async function handleInit( 8 | ctx: RequestContext, 9 | sessionManager: ClientSessionManager, 10 | auditSink?: AuditSink 11 | ): Promise { 12 | const request = ctx.body as any; 13 | 14 | if (request.tools && Array.isArray(request.tools)) { 15 | log.info('Client registering tools', { 16 | toolCount: request.tools.length, 17 | toolNames: request.tools.map((t: any) => t.name), 18 | }); 19 | 20 | for (const tool of request.tools) { 21 | if (!tool.name || typeof tool.name !== 'string') { 22 | ctx.throw(400, 'Invalid tool definition: name is required'); 23 | } 24 | if (!tool.description || typeof tool.description !== 'string') { 25 | ctx.throw(400, `Invalid tool definition for '${tool.name}': description is required`); 26 | } 27 | if (!tool.inputSchema || typeof tool.inputSchema !== 'object') { 28 | ctx.throw(400, `Invalid tool definition for '${tool.name}': inputSchema is required`); 29 | } 30 | } 31 | } 32 | 33 | const result = await sessionManager.initClient(request || {}); 34 | 35 | if (auditSink) { 36 | const event: AuditEvent = { 37 | eventId: randomUUID(), 38 | timestamp: Date.now(), 39 | clientId: (result as any).clientId, 40 | eventType: 'client_init', 41 | action: 'init', 42 | status: 'success', 43 | metadata: { 44 | clientInfo: request.clientInfo, 45 | toolsRegistered: request.tools ? request.tools.length : 0, 46 | toolNames: request.tools ? request.tools.map((t: any) => t.name) : [], 47 | }, 48 | }; 49 | await auditSink.write(event).catch(() => {}); 50 | } 51 | 52 | return result; 53 | } 54 | -------------------------------------------------------------------------------- /packages/server/src/index.ts: -------------------------------------------------------------------------------- 1 | export { AgentToolProtocolServer, createServer } from './create-server.js'; 2 | export { loadOpenAPI } from './openapi-loader.js'; 3 | export { loadGraphQL } from './graphql-loader.js'; 4 | export type { LoadGraphQLOptions, GraphQLAuthProvider } from './graphql-loader.js'; 5 | export { APIAggregator } from './aggregator/index.js'; 6 | export { SearchEngine } from './search/index.js'; 7 | export { SandboxExecutor } from './executor/index.js'; 8 | export type { 9 | ServerConfig, 10 | AuditConfig, 11 | Logger, 12 | Middleware, 13 | RequestContext, 14 | } from './core/config.js'; 15 | export { MB, GB, SECOND, MINUTE, HOUR, DAY } from './core/config.js'; 16 | export type { ToolRulesProvider } from './core/config.js'; 17 | 18 | export type { 19 | ProvenanceMetadata, 20 | SourceMetadata, 21 | ToolSource, 22 | LLMSource, 23 | UserSource, 24 | SystemSource, 25 | ReaderPermissions, 26 | ProvenanceState, 27 | PolicyAction, 28 | PolicyResult, 29 | SecurityPolicy, 30 | } from '@mondaydotcomorg/atp-provenance'; 31 | 32 | export { 33 | ProvenanceMode, 34 | ProvenanceSource, 35 | ProvenanceSecurityError, 36 | createProvenanceProxy, 37 | getProvenance, 38 | hasProvenance, 39 | getAllProvenance, 40 | canRead, 41 | getProvenanceForPrimitive, 42 | markPrimitiveTainted, 43 | isPrimitiveTainted, 44 | setProvenanceExecutionId, 45 | clearProvenanceExecutionId, 46 | cleanupProvenanceForExecution, 47 | captureProvenanceState, 48 | restoreProvenanceState, 49 | SecurityPolicyEngine, 50 | type Logger as ProvenanceLogger, 51 | preventDataExfiltration, 52 | preventDataExfiltrationWithApproval, 53 | requireUserOrigin, 54 | requireUserOriginWithApproval, 55 | blockLLMRecipients, 56 | blockLLMRecipientsWithApproval, 57 | auditSensitiveAccess, 58 | getBuiltInPolicies, 59 | getBuiltInPoliciesWithApproval, 60 | createCustomPolicy, 61 | instrumentCode, 62 | createTrackingRuntime, 63 | } from '@mondaydotcomorg/atp-provenance'; 64 | -------------------------------------------------------------------------------- /packages/server/src/utils/response.ts: -------------------------------------------------------------------------------- 1 | import { ServerResponse } from 'node:http'; 2 | 3 | /** 4 | * Sends a JSON response 5 | */ 6 | export function sendJson(res: ServerResponse, data: unknown, status = 200): void { 7 | res.writeHead(status, { 'Content-Type': 'application/json' }); 8 | res.end(JSON.stringify(data)); 9 | } 10 | 11 | /** 12 | * Sends an error response 13 | */ 14 | export function sendError( 15 | res: ServerResponse, 16 | error: string | Error, 17 | status = 500, 18 | requestId?: string 19 | ): void { 20 | const message = error instanceof Error ? error.message : error; 21 | sendJson( 22 | res, 23 | { 24 | error: message, 25 | ...(requestId && { requestId }), 26 | }, 27 | status 28 | ); 29 | } 30 | 31 | /** 32 | * Sends a 404 Not Found response 33 | */ 34 | export function send404(res: ServerResponse): void { 35 | sendJson(res, { error: 'Not found' }, 404); 36 | } 37 | 38 | /** 39 | * Sends a 400 Bad Request response 40 | */ 41 | export function sendBadRequest(res: ServerResponse, message: string): void { 42 | sendJson(res, { error: message }, 400); 43 | } 44 | 45 | /** 46 | * Sends a 503 Service Unavailable response 47 | */ 48 | export function sendServiceUnavailable(res: ServerResponse, message: string): void { 49 | sendJson(res, { error: message }, 503); 50 | } 51 | 52 | /** 53 | * Sets CORS headers on a response 54 | */ 55 | export function setCorsHeaders(res: ServerResponse, origin = '*'): void { 56 | res.setHeader('Access-Control-Allow-Origin', origin); 57 | res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); 58 | res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Client-ID'); 59 | res.setHeader('Access-Control-Max-Age', '86400'); 60 | } 61 | 62 | /** 63 | * Handles OPTIONS preflight requests 64 | */ 65 | export function handleOptions(res: ServerResponse): void { 66 | setCorsHeaders(res); 67 | res.writeHead(204); 68 | res.end(); 69 | } 70 | -------------------------------------------------------------------------------- /packages/atp-compiler/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/atp-compiler", 3 | "version": "0.19.19", 4 | "description": "Production-ready compiler for transforming async iteration patterns into resumable operations with checkpoint-based state management", 5 | "type": "module", 6 | "main": "dist/index.cjs", 7 | "module": "dist/index.js", 8 | "types": "dist/index.d.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./dist/index.d.ts", 12 | "import": "./dist/index.js", 13 | "require": "./dist/index.cjs" 14 | } 15 | }, 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/mondaycom/agent-tool-protocol", 22 | "directory": "packages/atp-compiler" 23 | }, 24 | "scripts": { 25 | "build": "npx tsc --build tsconfig.json && tsup", 26 | "build:tsc": "tsc", 27 | "test": "jest", 28 | "test:watch": "jest --watch", 29 | "test:coverage": "jest --coverage", 30 | "test:mutation": "stryker run", 31 | "lint": "tsc --noEmit", 32 | "clean": "rm -rf dist" 33 | }, 34 | "keywords": [ 35 | "agent-tool-protocol", 36 | "atp", 37 | "compiler", 38 | "resumable", 39 | "async", 40 | "checkpoint" 41 | ], 42 | "author": "", 43 | "license": "MIT", 44 | "dependencies": { 45 | "@babel/generator": "^7.26.0", 46 | "@babel/parser": "^7.26.0", 47 | "@babel/traverse": "^7.26.0", 48 | "@babel/types": "^7.26.0", 49 | "@mondaydotcomorg/atp-protocol": "0.19.17", 50 | "@mondaydotcomorg/atp-runtime": "0.19.16", 51 | "@types/babel__generator": "^7.6.0", 52 | "@types/babel__traverse": "^7.20.0" 53 | }, 54 | "peerDependencies": { 55 | "@mondaydotcomorg/atp-protocol": "0.19.17", 56 | "@mondaydotcomorg/atp-runtime": "0.19.16" 57 | }, 58 | "devDependencies": { 59 | "@stryker-mutator/core": "^8.0.0", 60 | "@types/jest": "^29.5.0", 61 | "fast-check": "^3.15.0", 62 | "jest": "^29.7.0", 63 | "tsup": "^8.5.1", 64 | "typescript": "^5.3.0" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /examples/test-server/README.md: -------------------------------------------------------------------------------- 1 | # ATP Test Server 2 | 3 | A minimal ATP server for testing and development, particularly useful for testing the LangChain integration. 4 | 5 | ## Features 6 | 7 | - Simple test APIs (`test.echo`, `test.add`) 8 | - Client services enabled (LLM, approval, embedding callbacks) 9 | - Quick startup for development and testing 10 | - Used by LangChain integration examples 11 | 12 | ## Usage 13 | 14 | ```bash 15 | # Start the test server 16 | NODE_OPTIONS='--no-node-snapshot' npx tsx server.ts 17 | 18 | # Server will start on http://localhost:3333 19 | ``` 20 | 21 | **Note**: The server uses a default JWT secret (`test-key`) for development. Set the `ATP_JWT_SECRET` environment variable for production use. 22 | 23 | **Important**: Use `NODE_OPTIONS='--no-node-snapshot'` to avoid segmentation faults with tsx. 24 | 25 | ## Test APIs 26 | 27 | ### `test.echo` 28 | 29 | Echoes back a message with timestamp. 30 | 31 | ```typescript 32 | await api.test.echo({ message: 'Hello' }); 33 | // Returns: { echoed: "Hello", timestamp: 1234567890 } 34 | ``` 35 | 36 | ### `test.add` 37 | 38 | Adds two numbers. 39 | 40 | ```typescript 41 | await api.test.add({ a: 5, b: 3 }); 42 | // Returns: { result: 8 } 43 | ``` 44 | 45 | ## Use with LangChain 46 | 47 | This server is perfect for testing the LangChain integration: 48 | 49 | ```bash 50 | # Terminal 1: Start test server 51 | cd examples/test-server 52 | NODE_OPTIONS='--no-node-snapshot' npx tsx server.ts 53 | 54 | # Terminal 2: Run LangChain examples 55 | cd examples/langchain-react-agent 56 | export OPENAI_API_KEY=sk-... 57 | yarn discover 58 | ``` 59 | 60 | ## Client Services 61 | 62 | The server enables client services, allowing ATP code to use: 63 | 64 | - `atp.llm.call()` - Routes to your LangChain LLM 65 | - `atp.approval.request()` - Triggers approval workflows 66 | - `atp.embedding.embed()` - Routes to your embeddings model 67 | 68 | Perfect for testing the full ATP + LangChain integration! 69 | -------------------------------------------------------------------------------- /packages/provenance/src/policies/schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | 3 | export const OperatorSchema = z.enum([ 4 | 'equals', 5 | 'notEquals', 6 | 'contains', 7 | 'notContains', 8 | 'startsWith', 9 | 'notStartsWith', 10 | 'endsWith', 11 | 'notEndsWith', 12 | 'matches', 13 | 'in', 14 | 'notIn', 15 | ]); 16 | 17 | export type Operator = z.infer; 18 | 19 | export const ConditionSchema = z.object({ 20 | field: z 21 | .string() 22 | .describe('Field to check (e.g. args.paramName, provenance.args.param.source.type)'), 23 | operator: OperatorSchema, 24 | value: z.any().describe('Value to compare against'), 25 | }); 26 | 27 | export type Condition = z.infer; 28 | 29 | export const PolicyActionSchema = z.enum(['log', 'approve', 'block']); 30 | 31 | export type PolicyAction = z.infer; 32 | 33 | export const PolicyRuleSchema = z.object({ 34 | id: z.string().optional(), 35 | action: PolicyActionSchema, 36 | conditions: z.array(ConditionSchema).describe('All conditions must match (implicit AND)'), 37 | reason: z.string().optional(), 38 | }); 39 | 40 | export type PolicyRule = z.infer; 41 | 42 | export const DeclarativePolicyConfigSchema = z.object({ 43 | id: z.string(), 44 | description: z.string().optional(), 45 | scope: z.object({ 46 | toolName: z.string().optional().describe('Regex pattern or exact match for tool name'), 47 | apiGroup: z.string().optional().describe('Regex pattern or exact match for API group'), 48 | }), 49 | rules: z.array(PolicyRuleSchema).describe('Rules are evaluated in order. First match wins.'), 50 | }); 51 | 52 | export type DeclarativePolicyConfig = z.infer; 53 | 54 | export const PolicyConfigurationSchema = z.object({ 55 | version: z.string(), 56 | policies: z.array(DeclarativePolicyConfigSchema), 57 | }); 58 | 59 | export type PolicyConfiguration = z.infer; 60 | -------------------------------------------------------------------------------- /packages/client/src/tools/explore-api.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { zodToJsonSchema } from 'zod-to-json-schema'; 3 | import type { AgentToolProtocolClient } from '../client.js'; 4 | import { ToolNames, type Tool } from './types.js'; 5 | 6 | export const exploreApiInputSchema = z.object({ 7 | path: z 8 | .string() 9 | .describe('Path to explore (e.g., "/", "/openapi/github", "/mcp/filesystem/read_file")'), 10 | }); 11 | 12 | type ExploreApiInput = z.infer; 13 | 14 | export function createExploreApiTool(client: AgentToolProtocolClient): Tool { 15 | return { 16 | name: ToolNames.EXPLORE_API, 17 | description: 18 | 'Explore APIs using filesystem-like navigation. Navigate through directories to discover available functions. Provide path as string like "/", "/openapi", "/openapi/github", or "/openapi/github/repos/createRepo" to see functions.', 19 | inputSchema: zodToJsonSchema(exploreApiInputSchema) as any, 20 | zodSchema: exploreApiInputSchema, 21 | func: async (input: ExploreApiInput) => { 22 | try { 23 | const result = await client.exploreAPI(input.path); 24 | 25 | if (result.type === 'directory') { 26 | return JSON.stringify( 27 | { 28 | success: true, 29 | type: 'directory', 30 | path: result.path, 31 | items: result.items, 32 | }, 33 | null, 34 | 2 35 | ); 36 | } else { 37 | return JSON.stringify( 38 | { 39 | success: true, 40 | type: 'function', 41 | name: result.name, 42 | description: result.description, 43 | definition: result.definition, 44 | group: result.group, 45 | path: result.path, 46 | }, 47 | null, 48 | 2 49 | ); 50 | } 51 | } catch (error: any) { 52 | return JSON.stringify( 53 | { 54 | success: false, 55 | error: error.message, 56 | }, 57 | null, 58 | 2 59 | ); 60 | } 61 | }, 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /examples/monday-graphql/agent.ts: -------------------------------------------------------------------------------- 1 | import { AgentToolProtocolClient } from '@mondaydotcomorg/atp-client'; 2 | 3 | async function main() { 4 | const client = new AgentToolProtocolClient({ 5 | baseUrl: 'http://localhost:3000', 6 | }); 7 | 8 | await client.init({ 9 | name: 'monday-graphql-agent', 10 | version: '1.0.0', 11 | }); 12 | 13 | console.log('🤖 Connecting to Monday.com GraphQL Agent...'); 14 | 15 | try { 16 | // Simple script to fetch boards and then items from the first board 17 | const script = ` 18 | // Fetch boards 19 | const boardsData = await api.monday.query_boards({ limit: 5 }); 20 | const boards = boardsData.boards || []; 21 | 22 | console.log(\`Found \${boards.length} boards\`); 23 | 24 | if (boards.length === 0) { 25 | return { message: 'No boards found' }; 26 | } 27 | 28 | const firstBoard = boards[0]; 29 | console.log(\`Fetching items for board: \${firstBoard.name} (ID: \${firstBoard.id})\`); 30 | 31 | // Fetch items for the first board 32 | // Note: We need to pass ids as an array of strings or numbers depending on schema 33 | // The schema usually expects [ID!] 34 | const itemsData = await api.monday.query_items({ 35 | ids: [firstBoard.id] 36 | }); 37 | 38 | const items = itemsData.items || []; 39 | console.log(\`Found \${items.length} items\`); 40 | 41 | return { 42 | board: { 43 | id: firstBoard.id, 44 | name: firstBoard.name, 45 | description: firstBoard.description 46 | }, 47 | itemsCount: items.length, 48 | sampleItems: items.slice(0, 3).map(item => ({ 49 | id: item.id, 50 | name: item.name 51 | })) 52 | }; 53 | `; 54 | 55 | console.log('🚀 Executing agent script...'); 56 | const result = await client.execute(script); 57 | 58 | console.log('\n✅ Execution Result:'); 59 | console.log(JSON.stringify(result, null, 2)); 60 | } catch (error) { 61 | console.error('❌ Error executing script:', error); 62 | } 63 | } 64 | 65 | main(); 66 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | push: 5 | branches: [master, main, develop] 6 | pull_request: 7 | branches: [master, main, develop] 8 | 9 | jobs: 10 | test: 11 | if: ${{ github.actor != 'atp-release[bot]' }} 12 | runs-on: ubuntu-latest 13 | 14 | strategy: 15 | matrix: 16 | node-version: [20.x, 22.x] 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | 21 | - name: Use Node.js ${{ matrix.node-version }} 22 | uses: actions/setup-node@v4 23 | with: 24 | node-version: ${{ matrix.node-version }} 25 | 26 | - name: Install dependencies 27 | run: yarn install --frozen-lockfile 28 | 29 | - name: Build 30 | run: yarn build 31 | 32 | - name: Run unit tests 33 | run: yarn test:unit 34 | 35 | - name: Run integration tests 36 | run: yarn test:integration 37 | 38 | # Note: We skip Jest e2e tests due to known isolated-vm + Jest worker 39 | # incompatibility. Integration tests provide complete coverage with 40 | # actual isolated-vm sandboxing (more reliable than Jest e2e). 41 | 42 | - name: Check types 43 | run: yarn build 44 | 45 | - name: Lint 46 | run: yarn lint || true 47 | 48 | integration-comprehensive: 49 | runs-on: ubuntu-latest 50 | 51 | steps: 52 | - uses: actions/checkout@v4 53 | 54 | - name: Use Node.js 22.x 55 | uses: actions/setup-node@v4 56 | with: 57 | node-version: 22.x 58 | 59 | - name: Install dependencies 60 | run: yarn install --frozen-lockfile 61 | 62 | - name: Build 63 | run: yarn build 64 | 65 | - name: Run comprehensive integration tests 66 | run: yarn test:integration 67 | 68 | - name: Upload test results 69 | if: always() 70 | uses: actions/upload-artifact@v4 71 | with: 72 | name: test-results 73 | path: | 74 | coverage/ 75 | *.log 76 | -------------------------------------------------------------------------------- /packages/mcp-adapter/src/schema-utils.ts: -------------------------------------------------------------------------------- 1 | import type { CustomFunctionDef } from '@mondaydotcomorg/atp-protocol'; 2 | 3 | export interface MCPToolSchema { 4 | type?: string; 5 | properties?: Record; 6 | required?: string[]; 7 | description?: string; 8 | [key: string]: unknown; 9 | } 10 | 11 | export interface MCPToolDefinition { 12 | name: string; 13 | description?: string; 14 | inputSchema?: MCPToolSchema; 15 | } 16 | 17 | export function convertMCPInputSchema(inputSchema: unknown): { 18 | type: string; 19 | properties?: Record; 20 | required?: string[]; 21 | [key: string]: unknown; 22 | } { 23 | const schema = inputSchema as MCPToolSchema | undefined; 24 | 25 | if (!schema) { 26 | return { type: 'object', properties: {} }; 27 | } 28 | 29 | const result: Record = {}; 30 | result.type = schema.type || 'object'; 31 | 32 | if (result.type === 'object') { 33 | result.properties = schema.properties || {}; 34 | } else if (schema.properties) { 35 | result.properties = schema.properties; 36 | } 37 | 38 | if (schema.required && schema.required.length > 0) { 39 | result.required = schema.required; 40 | } 41 | 42 | if (schema.description) { 43 | result.description = schema.description; 44 | } 45 | 46 | const knownFields = new Set(['type', 'properties', 'required', 'description']); 47 | for (const [key, value] of Object.entries(schema)) { 48 | if (!knownFields.has(key) && value !== undefined) { 49 | result[key] = value; 50 | } 51 | } 52 | 53 | return result as { 54 | type: string; 55 | properties?: Record; 56 | required?: string[]; 57 | [key: string]: unknown; 58 | }; 59 | } 60 | 61 | export function convertMCPToolToFunction( 62 | tool: MCPToolDefinition, 63 | handler: (input: unknown) => Promise 64 | ): CustomFunctionDef { 65 | return { 66 | name: tool.name, 67 | description: tool.description || `MCP tool: ${tool.name}`, 68 | inputSchema: convertMCPInputSchema(tool.inputSchema), 69 | handler, 70 | }; 71 | } 72 | -------------------------------------------------------------------------------- /packages/atp-compiler/src/plugin-system/default-plugins/promise-transformer-plugin.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Default Promise Transformer Plugin 3 | * Wraps the existing PromiseTransformer 4 | */ 5 | 6 | import * as t from '@babel/types'; 7 | import type { TransformationPlugin, BabelVisitor } from '../plugin-api.js'; 8 | import type { CompilerConfig, TransformMetadata } from '../../types.js'; 9 | import { PromiseTransformer } from '../../transformer/promise-transformer.js'; 10 | 11 | export class DefaultPromiseTransformerPlugin implements TransformationPlugin { 12 | name = 'atp-promise-transformer'; 13 | version = '1.0.0'; 14 | priority = 100; 15 | 16 | private transformer: PromiseTransformer; 17 | 18 | constructor(enableBatchParallel?: boolean) { 19 | this.transformer = new PromiseTransformer(enableBatchParallel); 20 | } 21 | 22 | getVisitor(config: CompilerConfig): BabelVisitor { 23 | return { 24 | CallExpression: (path: any) => { 25 | const node = path.node; 26 | if (this.isPromiseAllCall(node)) { 27 | this.transformer.transformPromiseAll(path); 28 | } else if (this.isPromiseAllSettledCall(node)) { 29 | this.transformer.transformPromiseAllSettled(path); 30 | } 31 | }, 32 | }; 33 | } 34 | 35 | getMetadata(): Partial { 36 | return { 37 | parallelCallCount: this.transformer.getTransformCount(), 38 | }; 39 | } 40 | 41 | reset(): void { 42 | this.transformer.resetTransformCount(); 43 | } 44 | 45 | private isPromiseAllCall(node: t.CallExpression): boolean { 46 | const callee = node.callee; 47 | return ( 48 | t.isMemberExpression(callee) && 49 | t.isIdentifier(callee.object, { name: 'Promise' }) && 50 | t.isIdentifier(callee.property, { name: 'all' }) 51 | ); 52 | } 53 | 54 | private isPromiseAllSettledCall(node: t.CallExpression): boolean { 55 | const callee = node.callee; 56 | return ( 57 | t.isMemberExpression(callee) && 58 | t.isIdentifier(callee.object, { name: 'Promise' }) && 59 | t.isIdentifier(callee.property, { name: 'allSettled' }) 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/protocol/src/oauth.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * OAuth and scope checking interfaces for Agent Tool Protocol 3 | */ 4 | 5 | /** 6 | * Scope checker interface 7 | * Checks what OAuth scopes a token has for a given provider 8 | */ 9 | export interface ScopeChecker { 10 | /** Provider name (e.g., 'github', 'google', 'microsoft') */ 11 | provider: string; 12 | 13 | /** 14 | * Check what scopes a token has 15 | * @param token - Access token to check 16 | * @returns Array of scope strings (e.g., ['repo', 'read:user']) 17 | */ 18 | check(token: string): Promise; 19 | 20 | /** 21 | * Validate if a token is still valid (optional) 22 | * @param token - Access token to validate 23 | * @returns true if valid, false if expired/revoked 24 | */ 25 | validate?(token: string): Promise; 26 | } 27 | 28 | /** 29 | * Token information returned by providers 30 | */ 31 | export interface TokenInfo { 32 | /** Whether the token is valid */ 33 | valid: boolean; 34 | 35 | /** OAuth scopes the token has */ 36 | scopes: string[]; 37 | 38 | /** Token expiration timestamp (milliseconds since epoch) */ 39 | expiresAt?: number; 40 | 41 | /** User identifier from the provider */ 42 | userId?: string; 43 | 44 | /** Additional provider-specific data */ 45 | metadata?: Record; 46 | } 47 | 48 | /** 49 | * Scope filtering configuration 50 | */ 51 | export interface ScopeFilteringConfig { 52 | /** Enable scope-based filtering */ 53 | enabled: boolean; 54 | 55 | /** 56 | * Filtering mode: 57 | * - 'eager': Filter tools at /api/definitions based on user's scopes 58 | * - 'lazy': Return all tools, validate scopes only at execution time 59 | */ 60 | mode: 'eager' | 'lazy'; 61 | 62 | /** 63 | * Cache TTL for scope checks in seconds 64 | * Default: 3600 (1 hour) 65 | */ 66 | cacheTTL?: number; 67 | 68 | /** 69 | * Fail behavior when scope checker not available for a provider 70 | * - 'allow': Allow all tools (no filtering) 71 | * - 'deny': Hide all tools requiring scopes 72 | */ 73 | fallback?: 'allow' | 'deny'; 74 | } 75 | -------------------------------------------------------------------------------- /packages/provenance/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './types.js'; 2 | 3 | export { 4 | createProvenanceProxy, 5 | getProvenance, 6 | hasProvenance, 7 | getAllProvenance, 8 | canRead, 9 | getProvenanceForPrimitive, 10 | markPrimitiveTainted, 11 | isPrimitiveTainted, 12 | setProvenanceExecutionId, 13 | clearProvenanceExecutionId, 14 | registerProvenanceMetadata, 15 | cleanupProvenanceForExecution, 16 | captureProvenanceState, 17 | restoreProvenanceState, 18 | captureProvenanceSnapshot, 19 | restoreProvenanceSnapshot, 20 | setGlobalProvenanceStore, 21 | hydrateProvenance, 22 | hydrateExecutionProvenance, 23 | } from './registry.js'; 24 | 25 | export { 26 | issueProvenanceToken, 27 | verifyProvenanceToken, 28 | verifyProvenanceHints, 29 | computeDigest, 30 | stableStringify, 31 | getClientSecret, 32 | type TokenPayload, 33 | } from './tokens.js'; 34 | 35 | export { SecurityPolicyEngine, type Logger } from './policies/engine.js'; 36 | 37 | export { 38 | preventDataExfiltration, 39 | preventDataExfiltrationWithApproval, 40 | requireUserOrigin, 41 | requireUserOriginWithApproval, 42 | blockLLMRecipients, 43 | blockLLMRecipientsWithApproval, 44 | auditSensitiveAccess, 45 | getBuiltInPolicies, 46 | getBuiltInPoliciesWithApproval, 47 | createCustomPolicy, 48 | } from './policies/engine.js'; 49 | 50 | export { 51 | createDeclarativePolicy, 52 | loadDeclarativePolicies, 53 | type DeclarativePolicyConfig, 54 | type PolicyConfiguration, 55 | type PolicyRule, 56 | type Condition, 57 | type Operator, 58 | } from './policies/declarative.js'; 59 | 60 | export { 61 | DeclarativePolicyConfigSchema, 62 | PolicyConfigurationSchema, 63 | PolicyRuleSchema, 64 | ConditionSchema, 65 | OperatorSchema, 66 | PolicyActionSchema, 67 | } from './policies/schema.js'; 68 | 69 | export { PolicyBuilder, RuleBuilder } from './policies/builder.js'; 70 | export { DynamicPolicyRegistry } from './policies/dynamic.js'; 71 | 72 | export { instrumentCode, createTrackingRuntime } from './ast/instrumentor.js'; 73 | 74 | export { type ProvenanceStore, InMemoryProvenanceStore } from './store.js'; 75 | -------------------------------------------------------------------------------- /packages/server/src/utils/context.ts: -------------------------------------------------------------------------------- 1 | import { IncomingMessage } from 'node:http'; 2 | import type { CacheProvider, AuthProvider, AuditSink } from '@mondaydotcomorg/atp-protocol'; 3 | import { log } from '@mondaydotcomorg/atp-runtime'; 4 | import type { RequestContext } from '../core/config.js'; 5 | import { parseQuery } from '../core/http.js'; 6 | 7 | export interface CreateContextOptions { 8 | req: IncomingMessage; 9 | cacheProvider?: CacheProvider; 10 | authProvider?: AuthProvider; 11 | auditSink?: AuditSink; 12 | customLogger?: any; 13 | responseHeaders: Map>; 14 | } 15 | 16 | /** 17 | * Creates a request context object with all necessary helpers and providers 18 | */ 19 | export function createContext(options: CreateContextOptions): RequestContext { 20 | const { req, cacheProvider, authProvider, auditSink, customLogger, responseHeaders } = options; 21 | 22 | const clientId = (req.headers['x-client-id'] as string) || undefined; 23 | const userId = (req.headers['x-user-id'] as string) || undefined; 24 | 25 | const url = req.url || '/'; 26 | const queryIndex = url.indexOf('?'); 27 | const path = queryIndex === -1 ? url : url.substring(0, queryIndex); 28 | 29 | return { 30 | method: req.method || 'GET', 31 | path, 32 | query: parseQuery(url), 33 | headers: req.headers as Record, 34 | body: null, 35 | status: 200, 36 | responseBody: null, 37 | clientId, 38 | userId, 39 | cache: cacheProvider, 40 | auth: authProvider, 41 | audit: auditSink, 42 | logger: customLogger || log, 43 | throw: (status, message) => { 44 | const error = new Error(message) as any; 45 | error.status = status; 46 | throw error; 47 | }, 48 | assert: (condition, message) => { 49 | if (!condition) { 50 | const error = new Error(message) as any; 51 | error.status = 400; 52 | throw error; 53 | } 54 | }, 55 | set: (header, value) => { 56 | if (!responseHeaders.has(req)) { 57 | responseHeaders.set(req, new Map()); 58 | } 59 | responseHeaders.get(req)!.set(header, value); 60 | }, 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /examples/langchain-react-agent/simple-test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple Integration Test - ATP + LangChain React Agent 3 | * 4 | * This example demonstrates: 5 | * - Creating ATP tools for LangChain agents 6 | * - Using all 3 ATP tools (search, fetch_all_apis, execute_code) 7 | * - Running code that calls APIs and makes LLM calls 8 | * 9 | * Prerequisites: 10 | * 1. Set OPENAI_API_KEY environment variable 11 | * 2. Start ATP server on http://localhost:3333 12 | * 13 | * Run: npx tsx simple-test.ts 14 | */ 15 | 16 | import { ChatOpenAI } from '@langchain/openai'; 17 | import { createReactAgent } from '@langchain/langgraph/prebuilt'; 18 | import { createATPTools } from '@mondaydotcomorg/atp-langchain'; 19 | 20 | async function main() { 21 | console.log('🧪 ATP + LangChain Integration Test\n'); 22 | 23 | try { 24 | const llm = new ChatOpenAI({ 25 | modelName: 'gpt-4o-mini', 26 | temperature: 0, 27 | openAIApiKey: process.env.OPENAI_API_KEY, 28 | }); 29 | 30 | const { tools } = await createATPTools({ 31 | serverUrl: 'http://localhost:3333', 32 | headers: { Authorization: 'Bearer test-key' }, 33 | llm, 34 | useLangGraphInterrupts: false, 35 | }); 36 | console.log(`✅ Created ${tools.length} tools: ${tools.map((t) => t.name).join(', ')}\n`); 37 | 38 | const agent = createReactAgent({ llm, tools }); 39 | 40 | const result = await agent.invoke({ 41 | messages: [ 42 | { 43 | role: 'user', 44 | content: `Use the ATP code execution tool to run this code: 45 | 46 | const sum = await api.test.add({ a: 5, b: 3 }); 47 | const joke = await atp.llm.call({ 48 | prompt: "Tell a ONE sentence joke about the number " + sum.result 49 | }); 50 | return { sum: sum.result, joke };`, 51 | }, 52 | ], 53 | }); 54 | 55 | const lastMsg = result.messages[result.messages.length - 1]; 56 | console.log('\n✅ Result:', lastMsg?.content); 57 | 58 | console.log('\n🎉 SUCCESS - ATP + LangChain works!\n'); 59 | } catch (error: any) { 60 | console.error('\n❌ FAILED:', error.message); 61 | console.error(error); 62 | process.exit(1); 63 | } 64 | } 65 | 66 | main(); 67 | -------------------------------------------------------------------------------- /.github/workflows/version-atp.yml: -------------------------------------------------------------------------------- 1 | name: ATP Version & Tag 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | 7 | jobs: 8 | version: 9 | if: ${{ github.actor != 'atp-release[bot]' }} 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write # needed to push commit + tags 13 | steps: 14 | - name: Checkout repository 15 | uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 0 18 | filter: tree:0 19 | 20 | - name: Install Node 21 | uses: actions/setup-node@v4 22 | with: 23 | node-version: 22 24 | registry-url: https://registry.npmjs.org/ 25 | 26 | - name: Enable Corepack 27 | run: corepack enable 28 | shell: bash 29 | 30 | - name: Setup Yarn 31 | run: corepack prepare yarn@stable --activate 32 | shell: bash 33 | 34 | - name: Get yarn cache directory path 35 | id: yarn-cache-dir-path 36 | run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT 37 | shell: bash 38 | 39 | - name: Cache yarn dependencies 40 | uses: actions/cache@v3 41 | with: 42 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }} 43 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 44 | restore-keys: | 45 | ${{ runner.os }}-yarn- 46 | 47 | - name: Install dependencies 48 | run: yarn install --immutable 49 | shell: bash 50 | 51 | # Create version commits and tags (non-interactive) 52 | - name: Version packages 53 | run: | 54 | git config user.name "atp-release[bot]" 55 | git config user.email "atp+github-actions[bot]@noreply.github.com" 56 | yarn nx release version 57 | 58 | # Push the version commit and tags so the tag-triggered publish workflow runs (config is controlled in nx.json) 59 | - name: Push commit and tags 60 | run: | 61 | git config user.name "atp-release[bot]" 62 | git config user.email "atp+github-actions[bot]@noreply.github.com" 63 | git push origin HEAD 64 | git push --tags 65 | -------------------------------------------------------------------------------- /.github/workflows/publish-atp.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*.*.*' 7 | - '*@*.*.*' 8 | - '@*/*@*.*.*' 9 | workflow_dispatch: # Allows manual triggering for testing 10 | 11 | jobs: 12 | publish: 13 | name: Publish ATP Ecosystem to NPM 14 | runs-on: ubuntu-latest 15 | permissions: 16 | contents: read 17 | id-token: write # needed for provenance data generation 18 | timeout-minutes: 20 19 | steps: 20 | - name: Checkout repository 21 | uses: actions/checkout@v4 22 | with: 23 | fetch-depth: 0 24 | filter: tree:0 25 | 26 | - name: Install Node 27 | uses: actions/setup-node@v4 28 | with: 29 | node-version: 22 30 | registry-url: https://registry.npmjs.org/ 31 | 32 | - name: Enable Corepack 33 | run: corepack enable 34 | shell: bash 35 | 36 | - name: Setup Yarn 37 | run: corepack prepare yarn@stable --activate 38 | shell: bash 39 | 40 | - name: Get yarn cache directory path 41 | id: yarn-cache-dir-path 42 | run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT 43 | shell: bash 44 | 45 | - name: Cache yarn dependencies 46 | uses: actions/cache@v3 47 | with: 48 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }} 49 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 50 | restore-keys: | 51 | ${{ runner.os }}-yarn- 52 | 53 | - name: Install dependencies 54 | run: yarn install --immutable 55 | shell: bash 56 | 57 | - name: Print Environment Info 58 | run: yarn nx report 59 | shell: bash 60 | 61 | - name: Build affected packages 62 | run: yarn build 63 | shell: bash 64 | 65 | - name: Check for publishable changes 66 | run: yarn nx release version --dry-run 67 | shell: bash 68 | 69 | - name: Publish packages 70 | run: yarn nx release publish 71 | shell: bash 72 | env: 73 | NODE_AUTH_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }} 74 | NPM_CONFIG_PROVENANCE: true 75 | -------------------------------------------------------------------------------- /packages/atp-compiler/src/types/compiler-interface.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Core compiler interface for ATP 3 | * All ATP compilers must implement this interface to ensure consistency 4 | */ 5 | 6 | import type { DetectionResult, TransformResult } from '../types.js'; 7 | 8 | /** 9 | * ICompiler - The core interface that all ATP compilers must implement 10 | * 11 | * This interface defines the contract for any compiler in the ATP system, 12 | * enabling dependency injection and easy extensibility. 13 | * 14 | * @example 15 | * ```typescript 16 | * class MyCustomCompiler implements ICompiler { 17 | * detect(code: string): DetectionResult { 18 | * // Detection logic 19 | * } 20 | * 21 | * transform(code: string): TransformResult { 22 | * // Transformation logic 23 | * } 24 | * 25 | * getType(): string { 26 | * return 'MyCustomCompiler'; 27 | * } 28 | * } 29 | * ``` 30 | */ 31 | export interface ICompiler { 32 | /** 33 | * Detect if code needs transformation and what patterns it contains 34 | * Can be synchronous or asynchronous 35 | */ 36 | detect(code: string): DetectionResult | Promise; 37 | 38 | /** 39 | * Transform the code based on detected patterns 40 | * Can be synchronous or asynchronous 41 | */ 42 | transform(code: string): TransformResult | Promise; 43 | 44 | /** 45 | * Get the compiler type identifier 46 | */ 47 | getType(): string; 48 | 49 | /** 50 | * Get cache statistics (optional) 51 | * Useful for performance monitoring and debugging 52 | */ 53 | getCacheStats?(): CacheStats | null; 54 | } 55 | 56 | /** 57 | * Cache statistics structure 58 | */ 59 | export interface CacheStats { 60 | size: number; 61 | enabled: boolean; 62 | } 63 | 64 | /** 65 | * Type guard to check if an object implements ICompiler 66 | */ 67 | export function isCompiler(obj: unknown): obj is ICompiler { 68 | return ( 69 | typeof obj === 'object' && 70 | obj !== null && 71 | 'detect' in obj && 72 | 'transform' in obj && 73 | 'getType' in obj && 74 | typeof (obj as any).detect === 'function' && 75 | typeof (obj as any).transform === 'function' && 76 | typeof (obj as any).getType === 'function' 77 | ); 78 | } 79 | -------------------------------------------------------------------------------- /examples/google-calendar-agent/mcp/README.md: -------------------------------------------------------------------------------- 1 | # MCP Agent (Direct Connection) 2 | 3 | This folder contains the MCP-based agent that connects **directly** to the Google Calendar MCP server. 4 | 5 | ## Architecture 6 | 7 | ``` 8 | ┌─────────────┐ 9 | │ Agent │ 10 | │ (LangChain) │ 11 | └──────┬──────┘ 12 | │ 13 | │ Direct Connection 14 | │ 15 | v 16 | ┌─────────────┐ 17 | │ MCP │ 18 | │ Server │ 19 | │ (Google │ 20 | │ Calendar) │ 21 | └─────────────┘ 22 | ``` 23 | 24 | ## Files 25 | 26 | - **`interactive-agent.ts`**: The main agent implementation 27 | 28 | ## Features 29 | 30 | - ✅ **Simple Setup**: No ATP server needed 31 | - ✅ **Direct MCP Connection**: Connects directly to `@cocal/google-calendar-mcp` 32 | - ✅ **Individual Tool Calls**: Each calendar operation is a separate tool call 33 | - ✅ **Transparent**: You see each tool execution separately 34 | - ✅ **Conversation Memory**: Maintains context across interactions 35 | 36 | ## Usage 37 | 38 | ```bash 39 | npm run chat:mcp 40 | ``` 41 | 42 | ## How It Works 43 | 44 | 1. **Agent** creates MCP connector to `@cocal/google-calendar-mcp` 45 | 2. **MCP Server** handles OAuth and Google Calendar API calls 46 | 3. **Agent** calls tools like `list-events`, `create-event` individually 47 | 4. Each tool call is executed separately and results are shown 48 | 49 | ## Example Interaction 50 | 51 | ``` 52 | You: What meetings do I have today? 53 | 54 | Agent thinking... 55 | → get-current-time({ timeZone: 'Asia/Jerusalem' }) 56 | → list-events({ calendarId: 'primary', timeMin: '2025-11-20T00:00:00', ... }) 57 | 58 | Agent: You have 3 meetings today: 59 | - 9:00 AM: Team Standup 60 | - 2:00 PM: Project Review 61 | - 4:00 PM: Client Call 62 | ``` 63 | 64 | ## Pros 65 | 66 | - Simple and straightforward 67 | - No server management needed 68 | - Easy to debug (individual tool calls) 69 | - Fast startup 70 | 71 | ## Cons 72 | 73 | - One tool call at a time 74 | - Can't combine operations in code 75 | - More verbose for complex queries 76 | - Agent must orchestrate multiple calls 77 | 78 | ## See Also 79 | 80 | - [ATP Agent](../atp/) - Code execution with multiple tools 81 | - [Authentication](../auth/) - OAuth setup 82 | -------------------------------------------------------------------------------- /packages/atp-compiler/src/transformer/array-transformer-utils.ts: -------------------------------------------------------------------------------- 1 | import * as t from '@babel/types'; 2 | import { isArrayMethod } from './utils.js'; 3 | 4 | /** 5 | * Find LLM call expression in AST node 6 | */ 7 | export function findLLMCallExpression(body: t.Node): t.CallExpression | null { 8 | let found: t.CallExpression | null = null; 9 | 10 | const visit = (node: t.Node) => { 11 | if (found) return; 12 | 13 | if (t.isAwaitExpression(node) && t.isCallExpression(node.argument)) { 14 | const call = node.argument; 15 | if (t.isMemberExpression(call.callee)) { 16 | found = call; 17 | return; 18 | } 19 | } 20 | 21 | Object.keys(node).forEach((key) => { 22 | const value = (node as any)[key]; 23 | if (Array.isArray(value)) { 24 | value.forEach((item) => { 25 | if (item && typeof item === 'object' && item.type) { 26 | visit(item); 27 | } 28 | }); 29 | } else if (value && typeof value === 'object' && value.type) { 30 | visit(value); 31 | } 32 | }); 33 | }; 34 | 35 | visit(body); 36 | return found; 37 | } 38 | 39 | /** 40 | * Get array method name from call expression 41 | */ 42 | export function getArrayMethodName(node: t.CallExpression): string | null { 43 | const arrayMethods = ['map', 'forEach', 'filter', 'reduce', 'find', 'some', 'every', 'flatMap']; 44 | for (const method of arrayMethods) { 45 | if (isArrayMethod(node, method)) { 46 | return method; 47 | } 48 | } 49 | 50 | return null; 51 | } 52 | 53 | /** 54 | * Get runtime method name for array method 55 | */ 56 | export function getRuntimeMethodName(arrayMethod: string): string | null { 57 | const mapping: Record = { 58 | map: 'resumableMap', 59 | forEach: 'resumableForEach', 60 | filter: 'resumableFilter', 61 | reduce: 'resumableReduce', 62 | find: 'resumableFind', 63 | some: 'resumableSome', 64 | every: 'resumableEvery', 65 | flatMap: 'resumableFlatMap', 66 | }; 67 | 68 | return mapping[arrayMethod] || null; 69 | } 70 | 71 | /** 72 | * Check if method can use batch parallel optimization 73 | */ 74 | export function canUseBatchParallel(methodName: string): boolean { 75 | return ['map', 'forEach', 'filter', 'find', 'some', 'every'].includes(methodName); 76 | } 77 | -------------------------------------------------------------------------------- /packages/atp-compiler/src/plugin-system/create-default-compiler.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Factory function to create a PluggableCompiler with all default plugins 3 | * 4 | * This makes PluggableCompiler a drop-in replacement for ATPCompiler 5 | */ 6 | 7 | import { PluggableCompiler } from './pluggable-compiler.js'; 8 | import { DefaultDetectionPlugin } from './default-plugins/detection-plugin.js'; 9 | import { DefaultLoopTransformerPlugin } from './default-plugins/loop-transformer-plugin.js'; 10 | import { DefaultArrayTransformerPlugin } from './default-plugins/array-transformer-plugin.js'; 11 | import { DefaultPromiseTransformerPlugin } from './default-plugins/promise-transformer-plugin.js'; 12 | import type { CompilerConfig } from '../types.js'; 13 | 14 | /** 15 | * Create a PluggableCompiler with all default ATP transformations 16 | * 17 | * This provides the same functionality as ATPCompiler but with plugin extensibility. 18 | * 19 | * @example 20 | * ```typescript 21 | * // Drop-in replacement for ATPCompiler 22 | * const compiler = createDefaultCompiler({ 23 | * enableBatchParallel: true, 24 | * maxBatchSize: 10, 25 | * }); 26 | * 27 | * // Works exactly like ATPCompiler 28 | * const result = await compiler.transform(code); 29 | * 30 | * // But you can also add custom plugins! 31 | * compiler.use(myCustomPlugin); 32 | * ``` 33 | */ 34 | export function createDefaultCompiler(config: Partial = {}): PluggableCompiler { 35 | const compiler = new PluggableCompiler(config); 36 | 37 | // Register default plugins that provide all ATP compiler functionality 38 | compiler.use(new DefaultDetectionPlugin()); 39 | compiler.use(new DefaultLoopTransformerPlugin(config.batchSizeThreshold)); 40 | compiler.use(new DefaultArrayTransformerPlugin(config.batchSizeThreshold)); 41 | compiler.use(new DefaultPromiseTransformerPlugin(config.enableBatchParallel)); 42 | 43 | return compiler; 44 | } 45 | 46 | /** 47 | * Type alias for backward compatibility 48 | * 49 | * This allows: 50 | * ```typescript 51 | * import type { ATPCompilerLike } from '@mondaydotcomorg/atp-compiler'; 52 | * 53 | * const compiler: ATPCompilerLike = createDefaultCompiler(); 54 | * ``` 55 | */ 56 | export type ATPCompilerLike = PluggableCompiler; 57 | -------------------------------------------------------------------------------- /examples/framework-integration/express-example.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Express Integration Example 3 | * Shows how to integrate ATP with Express and use Express middleware ecosystem 4 | */ 5 | 6 | import express from 'express'; 7 | import cors from 'cors'; 8 | // @ts-ignore - express-rate-limit types may not be available 9 | import rateLimit from 'express-rate-limit'; 10 | import { createServer } from '@mondaydotcomorg/atp-server'; 11 | 12 | const app = express(); 13 | const atpServer = createServer(); 14 | 15 | // Use Express's own middleware 16 | app.use( 17 | cors({ 18 | origin: '*', 19 | credentials: true, 20 | }) 21 | ); 22 | 23 | app.use( 24 | rateLimit({ 25 | windowMs: 15 * 60 * 1000, // 15 minutes 26 | max: 100, // Limit each IP to 100 requests per windowMs 27 | }) 28 | ); 29 | 30 | app.use(express.json()); 31 | 32 | // Custom authentication middleware using Express 33 | app.use((req, res, next) => { 34 | const apiKey = req.headers['x-api-key']; 35 | 36 | if (!apiKey) { 37 | // Optional - allow unauthenticated requests 38 | return next(); 39 | } 40 | 41 | const validKeys = process.env.API_KEYS?.split(',') || []; 42 | if (!validKeys.includes(apiKey as string)) { 43 | return res.status(403).json({ error: 'Invalid API key' }); 44 | } 45 | 46 | next(); 47 | }); 48 | 49 | // Add some custom tools 50 | atpServer.tool('greet', { 51 | description: 'Greet someone by name', 52 | input: { name: 'string' }, 53 | handler: async (input: unknown) => { 54 | const { name } = input as { name: string }; 55 | return { greeting: `Hello, ${name}!` }; 56 | }, 57 | }); 58 | 59 | // Mount ATP routes under /atp prefix - ATP expects /api/* routes 60 | // So /atp/api/info will be handled by ATP's /api/info 61 | app.use('/atp', atpServer.toExpress()); 62 | 63 | // Or mount at root 64 | // app.all('/api/*', atpServer.toExpress()); 65 | 66 | // Other Express routes 67 | app.get('/', (req, res) => { 68 | res.json({ 69 | message: 'ATP Server with Express', 70 | atpEndpoint: '/atp/api/info', 71 | }); 72 | }); 73 | 74 | const PORT = process.env.PORT || 3000; 75 | app.listen(PORT, () => { 76 | console.log(`Express server with ATP running on http://localhost:${PORT}`); 77 | console.log(`ATP Info: http://localhost:${PORT}/atp/api/info`); 78 | }); 79 | -------------------------------------------------------------------------------- /examples/simple-code-agent/README.md: -------------------------------------------------------------------------------- 1 | # Simple Code Agent Example 2 | 3 | A minimal example demonstrating how to use ATP chat utilities to build an interactive code execution agent. 4 | 5 | ## Features 6 | 7 | - Interactive console interface with syntax highlighting 8 | - Code execution with ATP runtime 9 | - Conversation memory 10 | - Clean, reusable utilities 11 | 12 | ## Setup 13 | 14 | 1. Make sure you have an ATP server running: 15 | 16 | ```bash 17 | cd path/to/your/atp-server 18 | npm start 19 | ``` 20 | 21 | 2. Create a `.env` file: 22 | 23 | ```bash 24 | OPENAI_API_KEY=your-openai-api-key 25 | ATP_SERVER_URL=http://localhost:3334 26 | ATP_AUTH_TOKEN=demo-token 27 | ``` 28 | 29 | 3. Install dependencies: 30 | ```bash 31 | npm install 32 | ``` 33 | 34 | ## Usage 35 | 36 | ```bash 37 | npm start 38 | ``` 39 | 40 | ## Code Overview 41 | 42 | This example shows the minimal code needed to create an interactive agent: 43 | 44 | ```typescript 45 | // 1. Create formatter and handler 46 | const formatter = new ChatFormatter(); 47 | const handler = new CodeExecutionHandler(formatter); 48 | 49 | // 2. Connect to ATP server 50 | const { client, tools } = await createATPTools({ serverUrl, ... }); 51 | 52 | // 3. Build system prompt inline with your domain-specific instructions 53 | const systemPrompt = `You are a helpful assistant with access to the ATP runtime. 54 | 55 | **Available APIs:** 56 | ${client.getTypeDefinitions()} 57 | 58 | **CRITICAL - Code Return Values:** 59 | - ⚠️ ALWAYS parse MCP responses with JSON.parse(result[0].text) before returning 60 | - ⚠️ Return CLEAN, PARSED objects - NOT raw MCP content arrays 61 | 62 | **When responding:** 63 | - Show clear, formatted results 64 | - Be concise and helpful`; 65 | 66 | // 4. Create agent 67 | const agent = createReactAgent({ 68 | llm, 69 | tools: [executeCodeTool], 70 | messageModifier: systemPrompt, 71 | }); 72 | 73 | // 5. Run interactive chat 74 | const chatRunner = new InteractiveChatRunner(formatter, handler); 75 | await chatRunner.run({ agent, threadId: 'session-id', formatter, handler }); 76 | ``` 77 | 78 | ## See Also 79 | 80 | - [ATP Chat Utilities](../utils) - Documentation for the utilities 81 | - [Google Calendar Agent](../google-calendar-agent) - More complex example 82 | -------------------------------------------------------------------------------- /packages/provenance/src/policies/builder.ts: -------------------------------------------------------------------------------- 1 | import type { DeclarativePolicyConfig, PolicyRule, Operator } from './declarative.js'; 2 | import type { PolicyAction } from '../types.js'; 3 | 4 | /** 5 | * Helper class to build policy rules fluently 6 | */ 7 | export class RuleBuilder { 8 | private rule: PolicyRule = { 9 | action: 'log', 10 | conditions: [], 11 | }; 12 | 13 | constructor(action: PolicyAction = 'log') { 14 | this.rule.action = action; 15 | } 16 | 17 | action(action: PolicyAction): this { 18 | this.rule.action = action; 19 | return this; 20 | } 21 | 22 | id(id: string): this { 23 | this.rule.id = id; 24 | return this; 25 | } 26 | 27 | reason(reason: string): this { 28 | this.rule.reason = reason; 29 | return this; 30 | } 31 | 32 | condition(field: string, operator: Operator, value: any): this { 33 | this.rule.conditions.push({ field, operator, value }); 34 | return this; 35 | } 36 | 37 | build(): PolicyRule { 38 | return this.rule; 39 | } 40 | } 41 | 42 | /** 43 | * Helper class to build declarative policies fluently 44 | */ 45 | export class PolicyBuilder { 46 | private config: DeclarativePolicyConfig; 47 | 48 | constructor(id: string) { 49 | this.config = { 50 | id, 51 | scope: {}, 52 | rules: [], 53 | }; 54 | } 55 | 56 | description(desc: string): this { 57 | this.config.description = desc; 58 | return this; 59 | } 60 | 61 | scopeTool(toolNamePattern: string): this { 62 | this.config.scope.toolName = toolNamePattern; 63 | return this; 64 | } 65 | 66 | scopeApiGroup(apiGroupPattern: string): this { 67 | this.config.scope.apiGroup = apiGroupPattern; 68 | return this; 69 | } 70 | 71 | /** 72 | * Add a rule using a builder callback 73 | * @example 74 | * .addRule(r => r.action('block').condition('args.amount', 'matches', '>1000')) 75 | */ 76 | addRule(buildFn: (builder: RuleBuilder) => RuleBuilder): this { 77 | const builder = new RuleBuilder(); 78 | this.config.rules.push(buildFn(builder).build()); 79 | return this; 80 | } 81 | 82 | /** 83 | * Add a fully formed rule object 84 | */ 85 | addRuleObject(rule: PolicyRule): this { 86 | this.config.rules.push(rule); 87 | return this; 88 | } 89 | 90 | build(): DeclarativePolicyConfig { 91 | return this.config; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /packages/langchain/src/tools.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * LangChain Integration for Agent Tool Protocol 3 | * 4 | * Converts ATP client tools into LangChain DynamicTool instances 5 | */ 6 | 7 | import { 8 | AgentToolProtocolClient, 9 | createToolsFromATPClient, 10 | type Tool, 11 | type ClientHooks, 12 | } from '@mondaydotcomorg/atp-client'; 13 | import { DynamicTool } from '@langchain/core/tools'; 14 | 15 | /** 16 | * Creates ATP client and returns LangChain-compatible DynamicTool instances 17 | * The client is automatically connected and ready to use. 18 | * 19 | * @param serverUrl - ATP server URL (e.g. 'http://localhost:3333') 20 | * @param headers - Optional headers for authentication (e.g. { Authorization: 'Bearer token' }) 21 | * @param hooks - Optional hooks for intercepting and modifying client behavior 22 | * @returns Promise of { client, tools } where tools is an array of LangChain DynamicTools 23 | * 24 | * @example 25 | * ```typescript 26 | * const { client, tools } = await createATPTools('http://localhost:3333', { 27 | * Authorization: 'Bearer api-key' 28 | * }); 29 | * 30 | * // Use tools with any LangChain agent 31 | * const agent = await createReactAgent({ llm, tools, prompt }); 32 | * const executor = new AgentExecutor({ agent, tools }); 33 | * ``` 34 | */ 35 | export async function createATPTools( 36 | serverUrl: string, 37 | headers?: Record, 38 | hooks?: ClientHooks 39 | ) { 40 | const client = new AgentToolProtocolClient({ baseUrl: serverUrl, headers, hooks }); 41 | await client.connect(); 42 | 43 | const atpTools = createToolsFromATPClient(client); 44 | 45 | const tools = atpTools.map( 46 | (tool: Tool) => 47 | new DynamicTool({ 48 | name: tool.name, 49 | description: tool.description || '', 50 | func: tool.func, 51 | }) 52 | ); 53 | 54 | return { client, tools }; 55 | } 56 | 57 | /** 58 | * Converts generic ATP tools into LangChain DynamicTool instances 59 | * 60 | * @param tools - Array of ATP tools (with inputSchema and func) 61 | * @returns Array of LangChain DynamicTools 62 | */ 63 | export function convertToLangChainTools(tools: Tool[]): DynamicTool[] { 64 | return tools.map( 65 | (tool: Tool) => 66 | new DynamicTool({ 67 | name: tool.name, 68 | description: tool.description || '', 69 | func: tool.func, 70 | }) 71 | ); 72 | } 73 | -------------------------------------------------------------------------------- /packages/client/src/core/types.ts: -------------------------------------------------------------------------------- 1 | export interface PreRequestContext { 2 | /** Request URL */ 3 | url: string; 4 | /** HTTP method */ 5 | method: string; 6 | /** Current headers that will be sent */ 7 | currentHeaders: Record; 8 | /** Request body (if any) */ 9 | body?: unknown; 10 | } 11 | 12 | export interface PreRequestResult { 13 | /** Updated headers to use for this request */ 14 | headers?: Record; 15 | /** If true, abort the request and throw an error */ 16 | abort?: boolean; 17 | /** Optional error message if aborting */ 18 | abortReason?: string; 19 | } 20 | 21 | /** 22 | * Hook called before every HTTP request to the ATP server 23 | * 24 | * Use this to: 25 | * - Refresh short-lived tokens 26 | * - Add tracing/correlation headers 27 | * - Log requests 28 | * - Implement custom authentication flows 29 | * - Conditionally abort requests 30 | * 31 | * @example 32 | * ```typescript 33 | * const preRequest = async (context) => { 34 | * // Refresh token before each request 35 | * const token = await auth.getAccessToken(); 36 | * 37 | * // Log the request 38 | * console.log(`[ATP] ${context.method} ${context.url}`); 39 | * 40 | * return { 41 | * headers: { 42 | * ...context.currentHeaders, 43 | * Authorization: `Bearer ${token}`, 44 | * 'X-Trace-Id': generateTraceId() 45 | * } 46 | * }; 47 | * }; 48 | * ``` 49 | */ 50 | export type PreRequestHook = (context: PreRequestContext) => Promise; 51 | 52 | /** 53 | * Client hooks for intercepting and modifying behavior 54 | * 55 | * @example 56 | * ```typescript 57 | * const hooks: ClientHooks = { 58 | * preRequest: async (context) => { 59 | * const token = await auth.getAccessToken(); 60 | * return { 61 | * headers: { 62 | * ...context.currentHeaders, 63 | * Authorization: `Bearer ${token}` 64 | * } 65 | * }; 66 | * } 67 | * }; 68 | * 69 | * const client = new AgentToolProtocolClient(serverUrl, {}, undefined, hooks); 70 | * ``` 71 | */ 72 | export interface ClientHooks { 73 | /** Hook called before every HTTP request */ 74 | preRequest?: PreRequestHook; 75 | // Future hooks can be added here without breaking changes: 76 | // postRequest?: PostRequestHook; 77 | // onError?: ErrorHook; 78 | // onRetry?: RetryHook; 79 | } 80 | -------------------------------------------------------------------------------- /packages/provenance/src/__tests__/dynamic-policy.test.ts: -------------------------------------------------------------------------------- 1 | import { DynamicPolicyRegistry } from '../policies/dynamic'; 2 | import { createDeclarativePolicy } from '../policies/declarative'; 3 | import { preventDataExfiltration } from '../policies/engine'; 4 | import type { ProvenanceMetadata } from '../types'; 5 | 6 | describe('DynamicPolicyRegistry', () => { 7 | it('should initialize with given policies', () => { 8 | const registry = new DynamicPolicyRegistry([preventDataExfiltration]); 9 | expect(registry.getPolicies()).toHaveLength(1); 10 | expect(registry.getPolicies()[0]?.name).toBe('prevent-data-exfiltration'); 11 | }); 12 | 13 | it('should add policies dynamically', () => { 14 | const registry = new DynamicPolicyRegistry(); 15 | registry.addPolicy(preventDataExfiltration); 16 | expect(registry.getPolicies()).toHaveLength(1); 17 | }); 18 | 19 | it('should remove policies', () => { 20 | const registry = new DynamicPolicyRegistry([preventDataExfiltration]); 21 | registry.removePolicy('prevent-data-exfiltration'); 22 | expect(registry.getPolicies()).toHaveLength(0); 23 | }); 24 | 25 | it('should check against all policies', async () => { 26 | const registry = new DynamicPolicyRegistry([preventDataExfiltration]); 27 | 28 | const mockGetProvenance = () => 29 | ({ 30 | id: '1', 31 | source: { type: 'tool', toolName: 'restricted-tool' }, 32 | readers: { type: 'restricted', readers: ['alice'] }, 33 | }) as any; 34 | 35 | // Should block because recipient 'bob' is not in readers ['alice'] 36 | const result = await registry.check( 37 | 'sendEmail', 38 | { to: 'bob', body: 'secret' }, 39 | mockGetProvenance 40 | ); 41 | 42 | expect(result.action).toBe('block'); 43 | expect(result.policy).toBe('prevent-data-exfiltration'); 44 | }); 45 | 46 | it('should load from declarative configs', async () => { 47 | const registry = new DynamicPolicyRegistry(); 48 | 49 | const config = { 50 | id: 'block-all', 51 | scope: {}, 52 | rules: [ 53 | { 54 | action: 'block' as const, 55 | conditions: [], // block everything 56 | }, 57 | ], 58 | }; 59 | 60 | registry.loadFromConfigs([config]); 61 | 62 | expect(registry.getPolicies()).toHaveLength(1); 63 | 64 | const result = await registry.check('anyTool', {}, () => null); 65 | expect(result.action).toBe('block'); 66 | }); 67 | }); 68 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node', 5 | roots: [''], 6 | testMatch: [ 7 | '**/__tests__/**/*.test.ts', 8 | '!**/packages/protocol/__tests__/**', 9 | '!**/packages/providers/__tests__/**', 10 | '!**/packages/server/__tests__/search-scope-filtering.test.ts', 11 | '!**/packages/server/__tests__/openapi-scope-extraction.test.ts', 12 | '!**/packages/atp-compiler/__tests__/**', 13 | ], 14 | testPathIgnorePatterns: ['/node_modules/', '/dist/'], 15 | setupFilesAfterEnv: ['/__tests__/setup.ts'], 16 | collectCoverageFrom: [ 17 | 'packages/*/src/**/*.ts', 18 | '!packages/*/src/**/*.d.ts', 19 | '!packages/*/src/index.ts', 20 | ], 21 | moduleNameMapper: { 22 | '^zod-to-json-schema$': '/__mocks__/zod-to-json-schema/index.js', 23 | '^@mondaydotcomorg/atp-protocol$': '/packages/protocol/src/index.ts', 24 | '^@mondaydotcomorg/atp-runtime$': '/packages/runtime/src/index.ts', 25 | '^@mondaydotcomorg/atp-provenance$': '/packages/provenance/src/index.ts', 26 | '^@mondaydotcomorg/atp-compiler$': '/packages/atp-compiler/src/index.ts', 27 | '^@mondaydotcomorg/atp-server$': '/packages/server/src/index.ts', 28 | '^@mondaydotcomorg/atp-server/(.*)$': '/packages/server/$1', 29 | '^@mondaydotcomorg/atp-client$': '/packages/client/src/index.ts', 30 | '^@mondaydotcomorg/atp-mcp-adapter$': '/packages/mcp-adapter/src/index.ts', 31 | '^@mondaydotcomorg/atp-langchain$': '/packages/langchain/src/index.ts', 32 | '^@mondaydotcomorg/atp-providers$': '/packages/providers/src/index.ts', 33 | // Force @babel/traverse to use compiled lib/index.js 34 | '^@babel/traverse$': '@babel/traverse/lib/index.js', 35 | }, 36 | transform: { 37 | '^.+\\.tsx?$': [ 38 | 'ts-jest', 39 | { 40 | tsconfig: { 41 | esModuleInterop: true, 42 | allowSyntheticDefaultImports: true, 43 | strict: false, 44 | }, 45 | useESM: false, 46 | }, 47 | ], 48 | }, 49 | testTimeout: 30000, 50 | verbose: true, 51 | maxWorkers: 1, 52 | workerIdleMemoryLimit: '512MB', 53 | extensionsToTreatAsEsm: [], 54 | resolver: '/jest-resolver.js', 55 | transformIgnorePatterns: [ 56 | // ALWAYS ignore @babel - use their compiled lib files 57 | 'node_modules/@babel/.*', 58 | ], 59 | }; 60 | -------------------------------------------------------------------------------- /packages/runtime/src/cache/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Cache API - Clean refactored version with decorators and extracted modules 3 | * 4 | * Benefits: 5 | * - No duplication between implementation and metadata 6 | * - Types auto-detected from TypeScript signatures 7 | * - Clean separation of concerns (backends, API) 8 | */ 9 | import { RuntimeAPI, RuntimeMethod } from '../metadata/decorators.js'; 10 | import { getCacheBackend } from './backends.js'; 11 | 12 | export type { CacheConfig, CacheBackend } from './types'; 13 | export { MemoryCacheBackend, RedisCacheBackend, initializeCache } from './backends.js'; 14 | 15 | /** 16 | * Cache Runtime API 17 | * 18 | * Store and retrieve data with optional TTL (Time To Live). 19 | * Supports in-memory (node-cache) and Redis backends. 20 | */ 21 | @RuntimeAPI('cache', 'Cache API - Store and retrieve data with optional TTL') 22 | class CacheAPI { 23 | /** 24 | * Gets a value from cache 25 | */ 26 | @RuntimeMethod('Get a value from cache by key', { 27 | key: { description: 'Cache key' }, 28 | }) 29 | async get(key: string): Promise { 30 | return getCacheBackend().get(key); 31 | } 32 | 33 | /** 34 | * Sets a value in cache with optional TTL in seconds 35 | */ 36 | @RuntimeMethod('Set a value in cache with optional TTL', { 37 | key: { description: 'Cache key' }, 38 | value: { description: 'Value to cache', type: 'unknown' }, 39 | ttl: { description: 'Time to live in seconds', optional: true }, 40 | }) 41 | async set(key: string, value: unknown, ttl?: number): Promise { 42 | return getCacheBackend().set(key, value, ttl); 43 | } 44 | 45 | /** 46 | * Deletes a value from cache 47 | */ 48 | @RuntimeMethod('Delete a value from cache', { 49 | key: { description: 'Cache key to delete' }, 50 | }) 51 | async delete(key: string): Promise { 52 | return getCacheBackend().delete(key); 53 | } 54 | 55 | /** 56 | * Checks if a key exists in cache 57 | */ 58 | @RuntimeMethod('Check if a key exists in cache', { 59 | key: { description: 'Cache key to check' }, 60 | }) 61 | async has(key: string): Promise { 62 | return getCacheBackend().has(key); 63 | } 64 | 65 | /** 66 | * Clears all cache entries 67 | */ 68 | @RuntimeMethod('Clear all cache entries') 69 | async clear(): Promise { 70 | return getCacheBackend().clear(); 71 | } 72 | } 73 | 74 | export const cache = new CacheAPI(); 75 | -------------------------------------------------------------------------------- /examples/vercel-ai-sdk-example/agent.ts: -------------------------------------------------------------------------------- 1 | import 'dotenv/config'; 2 | import { createATPTools } from '@mondaydotcomorg/atp-vercel-sdk'; 3 | import { openai } from '@ai-sdk/openai'; 4 | 5 | async function main() { 6 | const model = openai('gpt-4o-mini'); 7 | 8 | const { tools, client } = await createATPTools({ 9 | serverUrl: process.env.ATP_SERVER_URL || 'http://localhost:3333', 10 | headers: { 11 | Authorization: `Bearer ${process.env.ATP_API_KEY || 'test-key'}`, 12 | }, 13 | model, 14 | approvalHandler: async (message, context) => { 15 | console.log('\n🔔 Approval Request:'); 16 | console.log('Message:', message); 17 | if (context) { 18 | console.log('Context:', JSON.stringify(context, null, 2)); 19 | } 20 | 21 | return new Promise((resolve) => { 22 | process.stdin.once('data', (data) => { 23 | const answer = data.toString().trim().toLowerCase(); 24 | resolve(answer === 'y' || answer === 'yes'); 25 | }); 26 | console.log('\nApprove? (y/n): '); 27 | }); 28 | }, 29 | }); 30 | 31 | console.log('✅ ATP Client connected'); 32 | console.log('📋 Available tools:', Object.keys(tools).join(', ')); 33 | 34 | const { generateText } = await import('ai'); 35 | 36 | console.log('\n🤖 Agent ready! Executing task...\n'); 37 | 38 | const result = await generateText({ 39 | model, 40 | system: `You are a helpful assistant with access to ATP (Agent Tool Protocol). 41 | You can execute TypeScript code using the atp_execute_code tool. 42 | Within the code, you have access to: 43 | - atp.llm.call(prompt) - Call an LLM for sub-reasoning 44 | - atp.llm.extract(prompt, schema) - Extract structured data 45 | - atp.llm.classify(text, categories) - Classify text 46 | - atp.approval.request(message, context?) - Request human approval 47 | 48 | Use these capabilities to help users with complex tasks.`, 49 | prompt: `Use ATP to: 50 | 1. Call atp.llm.call() to generate a creative product idea 51 | 2. Use atp.approval.request() to ask if we should proceed with the idea 52 | 3. If approved, use atp.llm.call() again to create a marketing tagline for the product 53 | 4. Return the final result`, 54 | tools, 55 | maxSteps: 5, 56 | }); 57 | 58 | console.log('\n📊 Agent Result:'); 59 | console.log(JSON.stringify(result, null, 2)); 60 | 61 | process.exit(0); 62 | } 63 | 64 | main().catch((error) => { 65 | console.error('❌ Error:', error); 66 | process.exit(1); 67 | }); 68 | -------------------------------------------------------------------------------- /packages/atp-compiler/src/runtime/runtime-functions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Runtime Function Names 3 | * 4 | * These constants define the names of runtime functions used by the ATP compiler 5 | * when transforming code. They must match the implementations provided by the server. 6 | */ 7 | 8 | /** 9 | * Promise-related runtime functions 10 | */ 11 | export const RuntimeFunction = { 12 | // Promise operations 13 | RESUMABLE_PROMISE_ALL: 'resumablePromiseAll', 14 | RESUMABLE_PROMISE_ALL_SETTLED: 'resumablePromiseAllSettled', 15 | BATCH_PARALLEL: 'batchParallel', 16 | 17 | // Loop operations 18 | RESUMABLE_FOR_OF: 'resumableForOf', 19 | RESUMABLE_FOR_LOOP: 'resumableForLoop', 20 | RESUMABLE_WHILE: 'resumableWhile', 21 | 22 | // Array method operations 23 | RESUMABLE_MAP: 'resumableMap', 24 | RESUMABLE_FOR_EACH: 'resumableForEach', 25 | RESUMABLE_FILTER: 'resumableFilter', 26 | RESUMABLE_REDUCE: 'resumableReduce', 27 | RESUMABLE_FIND: 'resumableFind', 28 | RESUMABLE_SOME: 'resumableSome', 29 | RESUMABLE_EVERY: 'resumableEvery', 30 | RESUMABLE_FLAT_MAP: 'resumableFlatMap', 31 | } as const; 32 | 33 | export type RuntimeFunctionType = (typeof RuntimeFunction)[keyof typeof RuntimeFunction]; 34 | 35 | /** 36 | * Runtime functions that must execute inside the isolate (cannot cross boundary). 37 | * These receive Promise arguments or callback functions that can't be cloned. 38 | * 39 | * NOTE: BATCH_PARALLEL is NOT included because it receives serializable callback 40 | * descriptors and needs to communicate with the host for callback execution. 41 | */ 42 | export const IN_ISOLATE_RUNTIME_FUNCTIONS: readonly RuntimeFunctionType[] = [ 43 | RuntimeFunction.RESUMABLE_PROMISE_ALL, 44 | RuntimeFunction.RESUMABLE_PROMISE_ALL_SETTLED, 45 | RuntimeFunction.RESUMABLE_FOR_OF, 46 | RuntimeFunction.RESUMABLE_FOR_LOOP, 47 | RuntimeFunction.RESUMABLE_WHILE, 48 | RuntimeFunction.RESUMABLE_MAP, 49 | RuntimeFunction.RESUMABLE_FOR_EACH, 50 | RuntimeFunction.RESUMABLE_FILTER, 51 | RuntimeFunction.RESUMABLE_REDUCE, 52 | RuntimeFunction.RESUMABLE_FIND, 53 | RuntimeFunction.RESUMABLE_SOME, 54 | RuntimeFunction.RESUMABLE_EVERY, 55 | RuntimeFunction.RESUMABLE_FLAT_MAP, 56 | ]; 57 | 58 | /** 59 | * Check if a runtime function must execute inside the isolate 60 | */ 61 | export function isInIsolateRuntimeFunction(name: string): boolean { 62 | return IN_ISOLATE_RUNTIME_FUNCTIONS.includes(name as RuntimeFunctionType); 63 | } 64 | --------------------------------------------------------------------------------