The Azion MCP server operates as a bridge between AI assistants and the Azion Platform, providing secure access to documentation, tools, and resources through a standardized protocol.
Technical Architecture
MCP implements a client-server model using Anthropic’s Model Context Protocol. The architecture consists of three main components:
Technology Stack
| Component | Technology | Purpose |
|---|---|---|
| Runtime | Node.js 20+ | JavaScript execution environment |
| Language | TypeScript | Static typing and safety |
| Protocol | MCP SDK | Anthropic protocol implementation |
| Hosting | Functions | Distributed execution on Azion |
| Authentication | Personal Token / OAuth | Secure access control |
Communication Flow
AI Assistant (Client) ↓ HTTP/WebSocket ConnectionMCP Server (Function) ↓ API CallsAzion Platform (Resources)The flow works as follows:
- Connection: The MCP client establishes connection with the server using HTTP or WebSocket
- Authentication: The Personal Token validates the user’s identity
- Discovery: The client discovers available tools and resources
- Execution: The assistant invokes tools as needed
- Response: The server returns structured data to the client
MCP Components
The MCP protocol defines three main types of capabilities that a server can expose:
Tools
Tools are functions that the AI assistant can invoke to perform actions or fetch information. Each tool has:
- Name: Unique identifier (e.g.,
search_azion_docs_and_site) - Description: Explains the purpose and when to use it
- Input Schema: Defines expected parameters using JSON Schema
- Handler: Function that executes the logic
Example tool definition:
server.tool('search_azion_docs_and_site',{ description: 'Provides information about Azion Platform, products, and services', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Query to search documentation' }, docsAmount: { type: 'number', description: 'Number of documents to return', default: 5 } }, required: ['query'] }},async (args) => { // Search implementation const results = await searchDocs(args.query, args.docsAmount); return { content: [{ type: 'text', text: JSON.stringify(results) }] };});Resources
Resources are structured data that can be read by the client, similar to files. They use URIs for identification:
server.resource('static-site-deploy-guide','azion://static-site/deploy/step-0-preparation',async () => ({ contents: [{ uri: 'azion://static-site/deploy/step-0-preparation', name: 'step-0-preparation.md', mimeType: 'text/markdown', text: guideContent }]}));Resource URIs follow the format: azion://[category]/[resource]/[item]
Prompts
Prompts are pre-configured templates that help with common scenarios:
server.prompt('deploy-static-site',{ description: 'Step-by-step guide for deploying static sites', arguments: [ { name: 'framework', description: 'Framework used (e.g., nextjs, astro, hugo)', required: true } ]},async (args) => { return { messages: [{ role: 'user', content: { type: 'text', text: 'Help me deploy a ' + args.framework + ' site to Azion' } }] };});Implementing an MCP Server
To implement your own MCP server, follow these steps:
Project Structure
my-mcp-server/├── src/│ ├── index.ts # Entry point│ ├── core/│ │ ├── tools.ts # Tool definitions│ │ ├── resources.ts # Resource definitions│ │ ├── prompts.ts # Prompt definitions│ │ └── services/ # Business logic│ └── middlewares/│ └── auth.ts # Authentication├── package.json├── tsconfig.json└── azion.config.ts # Deploy configurationEntry Point
The main file initializes the server and registers capabilities:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';import { registerTools } from './core/tools';import { registerResources } from './core/resources';import { registerPrompts } from './core/prompts';
const server = new McpServer({name: 'my-mcp-server',version: '1.0.0'});
// Register capabilitiesregisterTools(server);registerResources(server);registerPrompts(server);
// Start serverexport default {async fetch(request: Request): Promise<Response> { return server.handleRequest(request);}};Authentication
The MCP server supports multiple authentication methods:
export async function authenticate(request: Request): Promise<AuthResult> {const authHeader = request.headers.get('Authorization');
if (!authHeader) { return { success: false, error: 'Token not provided' };}
const token = authHeader.replace('Bearer ', '');
// Verify Personal Token (format: azion + 35 chars)if (token.startsWith('azion') && token.length === 40) { return validatePersonalToken(token);}
// Verify OAuth token via SSOreturn validateOAuthToken(token);}Deploying to Azion
The MCP server can be deployed as a Function on Azion:
Configuration
Create an azion.config.ts file in the project root:
export default { build: { preset: 'typescript', polyfills: true }, functions: [ { name: '$FUNCTION_NAME', path: './functions/index.js' } ], applications: [ { name: '$APPLICATION_NAME', rules: { request: [ { name: 'Execute Function', description: 'Execute function for all requests', active: true, criteria: [ [ { variable: '${uri}', conditional: 'if', operator: 'matches', argument: '^/' } ] ], behaviors: [ { type: 'run_function', attributes: { value: '$FUNCTION_NAME' } } ] } ] }, functionsInstances: [ { name: '$FUNCTION_INSTANCE_NAME', ref: '$FUNCTION_NAME' } ] } ], workloads: [ { name: '$WORKLOAD_NAME', active: true, infrastructure: 1, deployments: [ { name: '$DEPLOYMENT_NAME', current: true, active: true, strategy: { type: 'default', attributes: { application: '$APPLICATION_NAME' } } } ] } ]}Deploy
Use the Azion CLI to deploy:
# Link projectazion link
# Build projectazion build
# Deploy to productionazion deployThe deploy creates a publicly accessible URL that can be configured in MCP clients.
Best Practices
Tool Design
- Descriptive names: Use clear verbs and nouns (e.g.,
search_docs,create_rule) - Typed parameters: Define complete JSON Schema schemas
- Clear descriptions: Explain when and how to use each tool
- Error handling: Return informative error messages
- Idempotency: Tools should be safe for multiple calls
Performance
- Response caching: Implement cache for frequently accessed data
- Pagination: Use pagination for large datasets
- Timeouts: Set appropriate timeouts for long operations
- Compression: Compress large responses
Security
- Input validation: Always validate input parameters
- Rate limiting: Implement rate limits per token
- Audit logs: Log all sensitive operations
- Sanitization: Remove sensitive data before returning
Complete Example
See a complete example of a documentation search tool:
import { z } from 'zod';
const SearchSchema = z.object({query: z.string().min(1),docsAmount: z.number().min(1).max(20).default(5)});
export async function searchDocumentation(args: unknown) {// Validate inputconst validated = SearchSchema.parse(args);
// Search documentsconst response = await fetch('https://api.azion.com/docs/search', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + process.env.AZION_API_KEY }, body: JSON.stringify({ query: validated.query, limit: validated.docsAmount })});
if (!response.ok) { throw new Error('Search failed: ' + response.statusText);}
const results = await response.json();
// Format responsereturn { content: [{ type: 'text', text: JSON.stringify(results, null, 2) }]};}Additional Resources
- MCP Specification - Official protocol documentation
- MCP SDK - Official TypeScript SDK
- Azion MCP Repository - Azion server source code
- MCP Overview - Introduction to MCP
- Configuration Guide - Set up your environment
- Practical Examples - Real-world use cases