@mondaydotcomorg/atp-server
v0.19.10
Published
Server implementation for Agent Tool Protocol
Maintainers
Readme
@mondaydotcomorg/atp-server
Production-ready ATP server with sandboxed execution, API aggregation, semantic search, and state management.
Overview
The ATP server provides secure, sandboxed TypeScript execution with built-in runtime APIs, OpenAPI integration, MCP support, semantic search, and comprehensive observability.
Installation
npm install @mondaydotcomorg/atp-serverArchitecture
graph TB
Server[AgentToolProtocolServer] --> Executor[SandboxExecutor]
Server --> Aggregator[APIAggregator]
Server --> Search[SearchEngine]
Server --> State[ExecutionStateManager]
Server --> Sessions[ClientSessionManager]
Executor --> Sandbox[VM2 Sandbox]
Executor --> Runtime[Runtime APIs]
Aggregator --> OpenAPI[OpenAPI Loader]
Aggregator --> MCP[MCP Adapter]
Aggregator --> Custom[Custom Functions]
Search --> Embeddings[Embedding Model]
State --> Cache[CacheProvider]Quick Start
Basic Server
import { createServer } from '@mondaydotcomorg/atp-server';
const server = createServer({
execution: {
timeout: 30000,
memory: 128 * 1024 * 1024, // 128MB
},
});
await server.start(3333);
console.log('ATP server running on http://localhost:3333');With OpenAPI Integration
import { createServer, loadOpenAPI } from '@mondaydotcomorg/atp-server';
const server = createServer();
// Load OpenAPI specs
const githubAPI = await loadOpenAPI({
url: 'https://api.github.com/openapi.json',
name: 'github',
auth: {
type: 'bearer',
token: process.env.GITHUB_TOKEN,
},
});
server.addAPIGroup(githubAPI);
await server.start(3333);
// Agents can now use:
// await atp.api.github.repos.get({ owner: 'user', repo: 'repo' })With MCP Support
import { MCPConnector } from '@mondaydotcomorg/atp-mcp-adapter';
const mcpConnector = new MCPConnector();
const filesystemAPI = await mcpConnector.connectToMCPServer({
name: 'filesystem',
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-filesystem', '/path/to/files'],
});
server.addAPIGroup(filesystemAPI);
// Agents can now use MCP tools:
// await atp.api.filesystem.read_file({ path: 'README.md' })With Semantic Search
import { OpenAIEmbeddings } from '@langchain/openai';
const embeddings = new OpenAIEmbeddings();
const server = createServer({
discovery: {
embeddings, // Enable semantic search
},
});
// Clients can search APIs semantically:
// client.searchQuery('How do I create a user?')With Redis Cache
import { RedisCache } from '@mondaydotcomorg/atp-providers';
import Redis from 'ioredis';
const redis = new Redis(process.env.REDIS_URL);
const server = createServer({
executionState: {
ttl: 3600, // 1 hour
},
});
server.setCacheProvider(
new RedisCache({
redis,
keyPrefix: 'atp:',
defaultTTL: 3600,
})
);
await server.start(3333);With Provenance Security
import {
ProvenanceMode,
preventDataExfiltration,
requireUserOrigin,
} from '@mondaydotcomorg/atp-server';
const server = createServer({
execution: {
provenanceMode: ProvenanceMode.PROXY, // or AST
securityPolicies: [preventDataExfiltration, requireUserOrigin],
},
});With Audit Logging
import { JSONLAuditSink } from '@mondaydotcomorg/atp-providers';
const server = createServer({
audit: {
enabled: true,
sinks: [
new JSONLAuditSink({
path: './audit-logs',
rotateDaily: true,
}),
],
},
});
// All execution, tool calls, LLM calls are loggedWith OpenTelemetry
const server = createServer({
otel: {
enabled: true,
serviceName: 'my-atp-server',
traceEndpoint: 'http://localhost:4318/v1/traces',
metricsEndpoint: 'http://localhost:4318/v1/metrics',
},
});
// Traces and metrics exported to OTLP collectorCustom APIs
Add Custom Functions
server.addAPIGroup({
name: 'database',
type: 'custom',
description: 'Database operations',
functions: [
{
name: 'createUser',
description: 'Create a new user',
inputSchema: {
type: 'object',
properties: {
name: { type: 'string' },
email: { type: 'string' },
},
required: ['name', 'email'],
},
handler: async (input) => {
const user = await db.users.create(input);
return user;
},
},
],
});
// Agents can use:
// await atp.api.database.createUser({ name: 'Alice', email: '[email protected]' })OAuth Integration
import { GoogleOAuthProvider } from '@mondaydotcomorg/atp-providers';
const oauthProvider = new GoogleOAuthProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
redirectUri: 'http://localhost:3333/oauth/callback',
scopes: ['https://www.googleapis.com/auth/userinfo.email'],
});
server.addAPIGroup({
name: 'gmail',
type: 'oauth',
oauthProvider,
functions: [
{
name: 'sendEmail',
description: 'Send email via Gmail',
inputSchema: {
/* ... */
},
handler: async (input, credentials) => {
// Use credentials.accessToken
return await sendGmailEmail(input, credentials.accessToken);
},
},
],
});Configuration
interface ServerConfig {
execution?: {
timeout?: number; // Default: 30000ms
memory?: number; // Default: 128MB
llmCalls?: number; // Max LLM calls per execution
provenanceMode?: ProvenanceMode; // Default: 'none'
securityPolicies?: SecurityPolicy[];
};
clientInit?: {
tokenTTL?: number; // Default: 1 hour
tokenRotation?: number; // Default: 30 minutes
};
executionState?: {
ttl?: number; // State TTL in seconds
maxPauseDuration?: number; // Max pause duration
};
discovery?: {
embeddings?: Embeddings; // Enable semantic search
};
audit?: {
enabled?: boolean;
sinks?: AuditSink[];
};
otel?: {
enabled?: boolean;
serviceName?: string;
traceEndpoint?: string;
metricsEndpoint?: string;
};
}API Groups
interface APIGroupConfig {
name: string;
type: 'openapi' | 'custom' | 'mcp' | 'oauth';
description?: string;
baseUrl?: string;
auth?: AuthConfig;
functions: CustomFunctionDef[];
oauthProvider?: OAuthProvider;
}Runtime APIs Available to Agents
Agents executing code have access to these runtime APIs:
atp.llm.*
// LLM calls (requires client.provideLLM())
await atp.llm.call({ prompt: 'Hello' });
await atp.llm.extract({ prompt: 'Extract', schema: { name: 'string' } });
await atp.llm.classify({ text: 'Text', categories: ['A', 'B'] });atp.approval.*
// Approval requests (requires client.provideApproval())
const result = await atp.approval.request('Delete files?', { critical: true });
if (result.approved) {
// Proceed
}atp.embedding.*
// Embeddings (requires client.provideEmbedding())
const id = await atp.embedding.embed('Store this text');
const results = await atp.embedding.search('query', { topK: 5 });atp.log.*
// Logging
atp.log.info('Processing user request');
atp.log.error('Failed to connect', { error });
atp.log.debug('Debug info', { data });atp.progress.*
// Progress reporting
atp.progress.report({ current: 5, total: 10, message: 'Processing...' });atp.cache.*
// Caching (requires cache provider)
await atp.cache.set('key', value, 3600);
const cached = await atp.cache.get('key');atp.api.*
// Dynamic API calls based on loaded API groups
await atp.api.github.repos.get({ owner: 'user', repo: 'repo' });
await atp.api.database.createUser({ name: 'Alice' });Middleware
import type { Middleware, RequestContext } from '@mondaydotcomorg/atp-server';
const loggingMiddleware: Middleware = async (context: RequestContext, next) => {
console.log(`${context.method} ${context.path}`);
const start = Date.now();
await next();
console.log(`Completed in ${Date.now() - start}ms`);
};
server.use(loggingMiddleware);Server Lifecycle
const server = createServer(config);
// Setup
server.setCacheProvider(cache);
server.setAuthProvider(auth);
server.addAPIGroup(apiGroup);
server.use(middleware);
// Start
await server.start(3333);
// Shutdown
await server.shutdown();Execution Flow
sequenceDiagram
participant Client
participant Server
participant Executor
participant Sandbox
participant APIs
Client->>Server: POST /execute
Server->>Executor: Execute code
Executor->>Sandbox: Create VM
loop Code execution
Sandbox->>APIs: atp.api.* call
APIs-->>Sandbox: Result
alt Needs LLM
Sandbox->>Server: Pause (LLM)
Server->>Client: Return paused
Client->>Server: Resume with LLM result
Server->>Sandbox: Continue
end
end
Sandbox-->>Executor: Result
Executor-->>Server: Execution complete
Server-->>Client: Return resultProduction Deployment
With Redis + PostgreSQL
import { RedisCache } from '@mondaydotcomorg/atp-providers';
import { PostgresSaver } from '@langchain/langgraph-checkpoint-postgres';
import Redis from 'ioredis';
const redis = new Redis(process.env.REDIS_URL);
const cache = new RedisCache({ redis });
const server = createServer({
execution: {
timeout: 60000,
memory: 256 * 1024 * 1024,
},
executionState: {
ttl: 7200, // 2 hours
},
audit: {
enabled: true,
},
otel: {
enabled: true,
},
});
server.setCacheProvider(cache);
await server.start(process.env.PORT || 3333);Security Best Practices
- Use provenance mode for sensitive data
- Set execution limits (timeout, memory, LLM calls)
- Enable audit logging for compliance
- Use OAuth for third-party APIs
- Validate API inputs with schemas
- Use security policies to block malicious patterns
TypeScript Support
Full TypeScript definitions included.
License
MIT
